线程池核心流程图

1、Synchronized和Violatile的本质区别?
1)Synchronized底层实现依赖于jvm的监视器monitor,对编译后的代码指令加锁。所以会出现阻塞情况。而Violatile底层实现则是借助于寄存器,也就是工作内存,在读取Violatile变量时,jvm会告诉寄存器,该变量的值需要同步到主内存,不会出现阻塞的情况。
2)线程池安全主要涉及两个方面:原子性和可见性。Synchronized既可以保证原子性,也可以保证可见性。而Violatile只能保证可见性,所以会存在线程安全问题。
3)Synchronized可以加锁级别可以是变量,方法,和类级别。而Violatile只能是变量级别。
2、线程池启动线程execute()和submit()方法有什么不同?
3、如何正确、优雅、合理的中断线程?
4、线程池底层实现?
线程池面试时涉及的问题比较多,我这里将线程池的覆盖范围做了总结,共五类问题:
- 线程池优势
- 线程池底层执行流程
- 线程池的三种队列
- 线程池的四种拒绝策略
- 线程池的**配置
一般初中级面试官会问一些线程池优势或底层执行流程,再高级的话就是队列原理和拒绝策略,以及项目中的实际配置。具体来看一下:
一)线程池优势:
java多线程的基础题

线程池最大的优势就是线程复用,避免了线程创建和销毁带来的性能损耗。特别是在数量多逻辑少的请求场景中,更能体现出优势。
二)线程池底层执行流程
首先初始化一定数量的线程,task任务进来,若没有线程执行,则放入队列。如果有线程,就将task任务和thread 封装成 worker,然后在worker启动线程执行task。当task执行完毕,worker中的线程不会马上销毁,而是去队列中获取task任务,如果有task存在,则执行,没有的话则看线程池设置策略。如果核心允许超时,则线程会一直阻塞,等待队列中有task进来,如果不允许超时,则核心线程执行销毁逻辑。
三)线程池的三种队列:
讯享网1)同步队列:SynchronousQueue,一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,该队列不是一种真正意义上的容器,其内部不维护task队列,不存储task任务,而是采用了传递的方式,由生产者将task传递给消费者。但也不能说SynchronousQueue没有维护队列,其内部维护的是一个线程队列,有线程队列,也就意味着有公平和不公平两种方式。在并发不大的情况下,该队列吞吐量通常要高于LinkedBlockingQueue,而在并发比较大的情况下,建议尽量不要该队列。容易引发内存溢出。静态工厂方法Executors.newCachedThreadPool使用了这个队列。
2)LinkedBlockingQueue,队列默认大小,两个重要参数:corePoolSize和maximumPoolSize。也是线程池工具类用的最多的一种队列,当corePoolSize和maximumPoolSize相等时,也就是创建了固定数量的线程池,没有核心线程和普通线程之分。
讯享网
3)ArrayBlockingQueue,该队列同LinkedBlockingQueue类似,只是基于数组实现,构造方法必须指定队列大小。最大的区别是ArrayBlockingQueue的生产者和消费者用的是相同的条件队列锁,在性能上可能略逊于LinkedBlockingQueue。
四)、线程池的四种拒绝策略
1)AbortPolicy,默认的一种拒绝策略,也是最简单的一种,采用了直接抛异常的方式。
讯享网
2)CallerRunsPolicy,直接运行被拒绝的任务,注意,这里是在线程池之外,脱离线程池运行的。有可能会导致性能下降,不建议使用。
3)DiscardPolicy,默默的丢弃task任务,不做任何处理。这会引起任务丢失,而开发人员又无从查起。当然,如果允许task丢失,可以选择此策略。
4)DiscardOldestPolicy,从名字可以看出,该策略会丢弃最老的一个task,然后重新提交。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/5438.html