java面试题:多线程与并发
多线程
关键词:线程池
Q:如何新建一个线程?
继承Thread,或者实现Runnable接口,或者通过Callable接口实现。
Q:Callable怎么用?
Callable可以作为FutureTask的方法参数。
FutureTask进行多线程操作时,还可以返回一个结果,也就是通过FutureTask实现异步。
Q:线程有哪些状态?
新建,就绪,运行,阻塞,停止
阻塞可以是sleep(),wait(),或者join()
Q: sleep() 和 wait() 的区别?
所属的类不一样。Thread.sleep(1000); 而wait()是属于Object的。
sleep()不会释放锁,而wait()会释放锁。
Q:死锁是怎么回事?
死锁,就是两个(或多个)线程对彼此加锁的资源进行加锁,导致彼此等待而永远阻塞。
比如,如果线程1锁住了A,然后尝试对B进行加锁,同时线程2已经锁住了B,接着尝试对A进行加锁,这时死锁就发生了。线程1永远得不到B,线程2也永远得不到A,并且它们永远也不会知道发生了这样的事情。为了得到彼此的对象(A和B),它们将永远阻塞下去。这种情况就是一个死锁。
Q:如何避免死锁?如何解决死锁?
破坏“不可剥夺”条件:一个进程不能获得所需要的全部资源时便处于等待状态,等待期间他占有的资源将被隐式的释放重新加入到 系统的资源列表中,可以被其他的进程使用,而等待的进程只有重新获得自己原有的资源以及新申请的资源才可以重新启动,执行。
破坏”请求与保持条件“:第一种方法静态分配即每个进程在开始执行时就申请他所需要的全部资源。第二种是动态分配即每个进程在申请所需要的资源时他本身不占用系统资源。
破坏“循环等待”条件:采用资源有序分配其基本思想是将系统中的所有资源顺序编号,将紧缺的,稀少的采用较大的编号,在申请资源时必须按照编号的顺序进行,一个进程只有获得较小编号的进程才能申请较大编号的进程。
Q:在实践中,有没有使用过多线程?
可以使用多线程同时执行多个任务,提高程序运行的效率。
还可以通过异步来处理耗时操作。比如一个线程做为主线程,新建另一个线程进行下载任务,这样主线程就不需要等待耗时操作。
Q:有三个线程,如何使它们顺序执行?
使用join,可以让某个线程在另一线程之前执行。
Q:假如有Thread1、Thread2、Thread3、Thread4四条线程分别统计C、D、E、F四个盘的大小,所有线程都统计完毕交给Thread5线程去做汇总,应当如何实现?
使用ForkJoinPool 。可以进行fork()分而治之,将任务进行分解,然后合并所有的结果。
Q:如何中断线程?中断线程意味着什么?
interrupt() 方法只是改变中断状态而已,它不会中断一个正在运行的线程。
如果线程被wait, join和sleep三种方法之一阻塞,此时调用该线程的interrupt()方法,那么该线程将抛出一个 InterruptedException中断异常(该线程必须事先预备好处理此异常),从而提早地终结被阻塞状态。
如果线程没有被阻塞,这时调用 interrupt()将不起作用,直到执行到wait(),sleep(),join()时,才马上会抛出 InterruptedException。
Q:线程池有没有了解过?为什么要用线程池?
新建线程的开销太大了,使用线程池可以节省系统资源。
Q:线程池的参数有哪些?
- 参数如下:
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
- corePoolSize:核心线程池里面的线程数量
- maximumPoolSize:线程池允许的最大线程数,它表示在线程池中最多能创建多少个线程;
- keepAliveTime:表示当线程池的个数大于核心数量corePoolSize时,线程的空闲时间达到指定的时间时会被销毁。
- unit:参数keepAliveTime的时间单位
- workQueue:一个阻塞队列,用来存储等待执行的任务。当请求的线程数大于corePoolSize时,线程会进入这个BlockingQueue阻塞队列。
- handler:执行拒绝策略的对象。当阻塞队列workQueue的任务缓存区到达上限,并且活动的线程数大于maximumPoolSize的时候,线程池会执行拒绝策略。
- threadFactory: 定义如何启动一个线程,可以设置线程的名称,并且可以确定是否是后台线程等。
Q:拒绝策略有哪些?
拒绝策略有以下几种:
ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。 (默认)
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列中等待最久的任务,然后把当前任务加入队列。
ThreadPoolExecutor.CallerRunsPolicy:由调用任务的run()方法绕过线程池执行此线程。
Q:阻塞队列有哪些?
Q:阻塞队列的默认值是多少?
ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列
LinkedBlockingQueue:一个基于链表结构的阻塞队列。LinkedBlockingQueue如果不指定大小,就是一个无界队列。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。
SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,静态工厂方法Executors.newCachedThreadPool使用了这个队列。
PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
Q:线程池有哪些类型?有什么不同?
1.newCachedThreadPool:
new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory);
newCachedThreadPool里面的corePoolSize核心线程数为0,最大线程数设置最大。它很灵活,但是要注意线程数量不要太大影响性能。
2.newFixedThreadPool:
ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
FixedThreadPool是 具有线程池提高程序效率和节省创建线程时所耗的开销的优点。
但是,在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。
3.newSingleThreadExecutor:
new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory));
newSingleThreadExecutor只允许一个线程。
4.newScheduledThreadPool:
newSingleThreadExecutor可以延迟执行。
Q:怎么手动实现一个线程池?
并发基础
关键词:线程安全、synchronized同步锁、Lock锁、volatile可见性、AtomicInteger原子操作类、CAS、AQS、ThreadLocal
Q:线程安全是什么?
多个线程操作同一共享变量时,需要保证数据的安全性。
Q:同步有哪些?
synchronized关键字和Lock锁。
Q:synchronized的底层实现?
每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
1、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。
2、如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.
3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
详情参见: https://www.cnblogs.com/paddix/p/5367116.html
Q:锁有哪些?
可重入锁ReentrantLock。可一个线程获得某个对象的方法的锁时,想要访问该对象的其他方法时无需再加锁。
ReentrantLock还可以设置为公平锁还是非公平锁。公平锁,会保证各个线程尽可能公平地拿到锁,不会导致某个线程一直拿不到锁的情况。
Q:ReentrantReadWriteLock是什么?读的时候可以写吗?读的时候可以读吗?写的时候可以写吗?
可重入的读写锁。读写锁分为读锁和写锁。
“读读共存,写写不共存,读写不共存”。
https://www.cnblogs.com/expiator/p/9374598.html
Q:AQS有没有了解过
AbstractQueueSynchronizer。抽象队列同步器。
CountDownLatch、Semaphore、Carrier这些并发工具类都是基于AQS实现的。线程池的内部也有继承自AQS的类。
Q:讲一下并发工具类是怎么使用的?
CountDownLatch是闭锁(阀门)。 更具体的待补充。。
Semaphore是信号量。
Carrier是 栅栏。
Q:有没有了解过CAS?
CAS就是Compare And Swap,比较和替换。
比如说,比较当前状态是否为开启状态,如果不是开启状态,就将其改为开启状态。
需要读写的内存值: V,进行比较的预估值: A,拟写入的更新值: B。
当且仅当 V == A 时, V = B。
Q:CAS原理是什么?
比较和替换。相当于有一个版本号,运用了乐观锁的机制。
Q:volatile关键字有什么用?
可以保证线程的可见性,线程修改共享变量时会被其他线程发现。还可以禁止指令重排序。
Q:volatile是怎么实现的?
这个涉及到Java内存模型。JMM。
详情见: https://www.cnblogs.com/xrq730/p/7048693.html
Q:volatile能保证线程安全吗?
不能。volatile只有进行原子操作时,才是线程安全的
Q:使用volatile操作i++,是否线程安全?如果不安全,应该怎么处理?
线程不安全。因为i++不是原子操作。
可以使用AtomicInteger原子操作类进行操作。
Q:volatile和全局变量有什么区别?
Q:AtomicInteger是怎么实现的?
CAS乐观锁机制。比较和替换实现。
Q:讲一下ThreadLocal
每个线程都有一个自己的副本变量。
Q:讲一下ThreadLocal的底层实现。
Q:ThreadLocal是如何为每个线程创建变量的副本的?
Q:ThreadLocal是如何做到在不同线程set()、get()的值不被其它线程访问的;
各线程对共享的ThreadLocal实例进行操作,实际上是以该实例为键对内部持有的ThreadLocalMap对象进行操作。
首先,在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。
初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。
然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。
Q:ThreadLocal可能会导致哪些问题?怎么解决?
内存泄露。用完记得将没用的ThreadLocal运行remove移除。
未完待续
更详细的资料参见 :
想进大厂需要懂的50个多线程面试题
java面试题:多线程与并发的更多相关文章
- Java基础技术多线程与并发面试【笔记】
Java基础技术多线程与并发 什么是线程死锁? 死锁是指两个或两个以上的进程(线程)在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去,我们就可以称 ...
- [ Java面试题 ]多线程篇
1.什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速.比如,如果一个线程完成一 ...
- Java面试题-多线程
1. java中有几种方法可以实现一个线程? 多线程有两种实现方法,分别是继承Thread类与实现Runnable接口. 这两种方法的区别是,如果你的类已经继承了其它的类,那么你只能选择实现Runna ...
- java中的多线程高并发与负载均衡的用途
感觉对于这两问题的描述,大家很迷惑把 .下面我就介绍一下: 一; 什么是java的高并发,在什么情况下产生的? 答:如果网站的访问量非常大的话,我们就应该考虑高并发的情况. 高并发的时候就是有很多用户 ...
- Java面试题阶段汇总
初级面试题 Java面试题-基础篇一 Java面试题-基础篇二 Java面试题-集合框架篇三 Java面试题-基础篇四 Java面试题-基础篇五 Java面试题-javaweb篇六 Java面试题 ...
- Java面试题(全)--视频系列
此系列为面试笔试题的视频讲解,以下均为超链接,点击即可进入每个知识点的讲解. Java面试题01.面试的整体流程 Java面试题02.java的垮平台原理 Java面试题03.搭建一个java的开发环 ...
- 最全最新java面试题系列全家桶(带答案)
最全最新java面试题系列全家桶(带答案) 置顶 2019年04月06日 22:40:28 青春季风暴 阅读数 14082 文章标签: java面试题技术栈 更多 分类专栏: 面试 版权声明:本文 ...
- Java面试题整理一(侧重多线程并发)
1..是否可以在static环境中访问非static变量? 答:static变量在Java中是属于类的,它在所有的实例中的值是一样的.当类被Java虚拟机载入的时候,会对static变量进行初始化.如 ...
- 2020年Java多线程与并发系列22道高频面试题(附思维导图和答案解析)
前言 现在不管是大公司还是小公司,去面试都会问到多线程与并发编程的知识,大家面试的时候这方面的知识一定要提前做好储备. 关于多线程与并发的知识总结了一个思维导图,分享给大家 1.Java中实现多线程有 ...
- 面试题_1_to_16_多线程、并发及线程的基础问题
多线程.并发及线程的基础问题 1)Java 中能创建 volatile 数组吗?能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组.我的意思是,如果改变引 ...
随机推荐
- Dubbo(1)--初识Dubbo
1. 为什么需要 Dubbo 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用架构 当 ...
- snmp安装,及测试
https://www.cnblogs.com/xdp-gacl/p/4016524.html
- 10. js时间格式转换
{ field : 'CREATE_TIME', width : fixWidth(0.10), title : '创建时间', align : 'center', hidden: ...
- HTML+CSS盒模型
一.Padding 1.padding用来调整内容在容器中的位置关系:padding的属性要添加到父元素上. padding值是额外加在元素原有的大小之上的,若想保证元素大小不变,需从元素宽或高上 ...
- leetcode999
class Solution: def numRookCaptures(self, board: 'List[List[str]]') -> int: basei = 0 basej = 0 r ...
- System.Types.hpp(77): E2029 'TObject' must be a previously defined class or struct
System.Types.hpp System.Types.hpp(77): E2029 'TObject' must be a previously defined class or struct ...
- jquery 基础-记住
jquery最为一个库,简便. 难点在于选择器,筛选器的使用. 属性一般都是,jquery对象.函数(),括号内部添属性. s= '<tr> <td class="fix& ...
- curator 实现分布式一致性锁
最近准备在项目中引入分布式锁,故而研究基于zookeeper的curator框架. 网上资料不多,自己研究其源码发现,这个框架已经帮我做了很多现成的实现. 下面介绍下锁的实现: 通过源码中Lockin ...
- Erlang 笔记
集成开发环境:IntelliJ IDEA的Erlang插件 教程:www.erlang-cn.com/462.html,寻找erlang程序设计第2版pdf f():释放之前绑定过的所有变量. -ex ...
- ACM__队列
今天学回顾bfs的时候遇到了,遂总结一下 队列是一种特殊的线性表,只允许在队列的前端(front)进行删除操作,在队尾进行插入操作,进行插入操作的端称作队尾,进行删除操作的端称作对头.(来自百度百科) ...