概述
- 使用线程池技术可以降低资源的消耗,提高响应速度和线程的可重复利用性
- 当提交一个新任务到线程池后,线程池首先会判断核心线程池(
corePoolSize
)里的线程是否都在执行任务,如果不是则创建一个新的工作线程来执行任务。如果核心线程池corePoolSize
的线程都被占用在执行任务,线程判断工作队列是否已满,如果工作队列没有满:则将新提交的任务存储到工作队列中,如果工作队列已满:判断线程池(maximumPoolSize
)的线程是否处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果线程池已满,则交给饱和策略处理这个任务
线程池的五种状态
RUNNING(运行中)
:线程池处在RUNNING
状态时,能够接收新任务,以及对已添加的任务进行处理。线程池的初始化状态是RUNNING。SHUTDOWN(关掉)
:调用线程池的shutdown()
接口时,线程池由RUNNING -> SHUTDOWN
。处在SHUTDOWN
状态时,不接收新任务,但能处理已添加的任务。STOP(停止):
调用线程池的shutdownNow
()接口时,线程池由(RUNNING or SHUTDOWN
)-> STOP
。处在STOP
状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。tidying
:当线程池在SHUTDOWN
状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由SHUTDOWN -> TIDYING
。 当线程池在STOP
状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING
。terminated
(终止):线程池彻底终止,就变成terminated
状态。 线程池处在tidying
状态时,执行完terminated()
之后,就会由tidying -> terminated
。
线程池的参数
corePoolSize
: 初始化指定的核心线程数量maximumPoolSize
:允许的最大线程数。当前的线程数小于maximumPoolSize
,则会新建线程来执行任务keepAliveTime
:线程空闲的时间unit
:keepAliveTime的单位workQueue
:保存等待执行的任务的阻塞队列。初始化核心线程池已满时,队列未满会吧任务存储到队列中。可供选择的几种阻塞队列
ArrayBlockingQueue
:是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。LinkedBlockingQueue
:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。SynchronousQueue
:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。PriorityBlockingQueue
:一个具有优先级得无限阻塞队列threadFactory
:用于设置创建线程的工厂。不指定 则是默认handler
:线程池的拒绝策略。线程池中的线程已经饱和了,而且阻塞队列也已经满了,则线程池会选择一种拒绝策略来处理该任务
线程池提供的
四种拒绝策略
,也可以实现自己的拒绝策略:
AbortPolicy
:默认策略 抛出异常CallerRunsPolicy
:由当前调用者所在的线程来执行任务DiscardOldestPolicy
:丢弃阻塞队列中靠最前的任务,并执行当前任务DiscardPolicy
:直接丢弃多余的任务
1 | ThreadPoolExecutor executor=new |
常用方法
getCorePoolSize()
返回核心线程数。getMaximumPoolSize()
返回允许的最大线程数。getPoolSize()
返回池中的当前线程数。getQueue()
返回此执行程序使用的任务队列。isShutdown()
如果此执行程序已关闭,则返回 true。isTerminated()
如果关闭后所有任务都已完成,则返回 true。execute(Runnable command)
在将来某个时间执行给定任务shutdown()
按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。shutdownNow()
尝试停止所有的活动执行任务、暂停等待任务的处理,并返回等待执行的任务列表。
自定义线程名称
1 | public class ThreadPoolExecutorTest { |
源码分析
类中其他属性
1 |
|
构造方法
1 | public ThreadPoolExecutor(int corePoolSize, |
提交任务
1 | /* |
addWorker
原子性的增加workerCount。
将用户给定的任务封装成为一个worker,并将此worker添加进workers集合中。
启动worker对应的线程,并启动该线程,运行worker的run方法。
回滚worker的创建动作,即将worker从workers集合中删除,并原子性的减少workerCount。
1 | private boolean addWorker(Runnable firstTask, boolean core) { |
执行任务
runWorker函数中会实际执行给定任务(即调用用户重写的run方法),并且当给定任务完成后,会继续从阻塞队列中取任务,直到阻塞队列为空(即任务全部完成)。在执行给定任务时,会调用钩子函数,利用钩子函数可以完成用户自定义的一些逻辑。在runWorker中会调用到getTask函数和processWorkerExit钩子函数
1 | final void runWorker(Worker w) { |
此函数用于从workerQueue阻塞队列中获取Runnable对象,由于是阻塞队列,所以支持有限时间等待(poll)和无限时间等待(take)。在该函数中还会响应shutDown和、shutDownNow函数的操作,若检测到线程池处于SHUTDOWN或STOP状态,则会返回null,而不再返回阻塞队列中的Runnalbe对象。
1 | private Runnable getTask() { |
processWorkerExit函数是在worker退出时调用到的钩子函数,而引起worker退出的主要因素如下
阻塞队列已经为空,即没有任务可以运行了。
调用了shutDown或shutDownNow函数
此函数会根据是否中断了空闲线程来确定是否减少workerCount的值,并且将worker从workers集合中移除并且会尝试终止线程池。
1 | private void processWorkerExit(Worker w, boolean completedAbruptly) { |
关闭线程池
1 | public void shutdown() { |
1 | final void tryTerminate() { |
1 | private void interruptIdleWorkers(boolean onlyOne) { |