前言
最近在准备面试资料,就看了一下多线程相关的文章,但是找了很多文章发现大家写的差不多一样,有的文章同样的内容,但是给出的答案却是不一样的,所有我就自己参考一些自己买的书籍和看一下源码总结了一下,也就是以下内容。
这里都是线程池相关的内容,也就是ThreadPoolExecutor这个类相关的内容,至于Executors框架,我会单独再写一篇文章进行详细的写一下,也作为自己的面试总结。
一、线程池的实现原理
1、当提交一个任务到线程池时,线程池的处理流程
1、判断核心线程池里的核心线程是否已满
- 是,判断工作队列是否已经满了
- 否,不管核心线程有没有空闲,都创建一个新的线程执行这个任务
2、工作队列是否已经满了
- 已满,判断线程池是否满了
- 未满,将任务存储在工作队列里
3、判断线程池是否满了【核心线程以外的可以创建的线程,最大线程数】
- 已满,交给饱和策略
handle
处理无法执行的任务- 未满,创建一个新的线程执行这个任务
以上流程的图解
1、 线程池刚创建时是没有线程的,并且里面包含了一个任务队列。
2、 小于核心线程数(
corePoolSize
),不管有没有空闲的核心线程任务来了都创建一个新的线程;3、 大于等于核心线程数(
corePoolSize
)且小于设置的最大线程数(maximumPoolSize
),先加入到任务队列(workQueue
)里;4、 队列满了再继续创建线程,直到线程数到达设置的最大线程数(
maximumPoolSize
);5、 如果达到最大线程数(
maximumPoolSize
)且任务队列(workQueue
)满了,则通过 handler 所指定的饱和策略来处理此任务;6、 当线程池中的线程数量大于核心线程数(
maximumPoolSize
)时,如果某个线程空闲时间超过keepAliveTime
,线程将被终止,这样线程池可以动态的调整池中的线程数。
2、ThreadPoolExecutor
执行executor()
方法的四种
情况
1、 如果当前运行的线程少于
corePoolSize
,则创建新的线程来执行任务【全局锁】2、 如果运行的线程数大于等于
corePoolSize
,则将任务加入BlockingQueue
阻塞队列3、 如果
BlockingQueue
阻塞队列已满,无法加入新的任务,则创建新的线程来处理【全局锁】4、 如果创建的新的线程促使正在运行的线程数超过了
maximumPoolSize
,任务将被拒绝,并调用RejectedExecutionHandler
的rejectedExecution()
方法
3、线程池里的线程执行任务分两种情况
1、在
executor()
方法中创建一个线程,会让这个线程执行当前任务2、线程在执行完当前任务以后,队列里有任务就会不停的从
BlockingQueue
中取任务执行。
二、线程池的使用
1、线程池的创建
1.1、new 一个ThreadPoolExecutor调用的构造方法的源码
public ThreadPoolExecutor(i