从ThreadPoolExecutor源码理解线程池
线程池的状态:
线程有五种状态:新建,就绪,运行,阻塞,死亡,线程池同样有五种状态:RUNNING, SHUTDOWN, STOP, TIDYING, TERMINATED。
RUNNING:处于RUNNING状态的线程池能够接受新任务,以及对新添加的任务进行处理。
SHUTDOWN:处于SHUTDOWN状态的线程池不可以接受新任务,但是可以对已添加的任务进行处理。
STOP:处于STOP状态的线程池不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
TIDYING:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
TERMINATED:线程池彻底终止的状态。

ThreadPoolExecutor的execute方法:(来到线程池的线程会被封装成ThreadPoolExecutor.Worker对象,Worker也是实现类Runnable接口的,所以它本身也是一个线程)
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get();//执行1 if (workerCountOf(c) < corePoolSize) {//执行2 if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) {//执行3 int recheck = ctl.get(); if (! isRunning(recheck) && remove(command))//执行4 reject(command); else if (workerCountOf(recheck) == 0)//执行5 addWorker(null, false); } else if (!addWorker(command, false))//执行6 reject(command);
}
代码的具体流程:
- 获取线程池的状态。
- 如果线程池当前线程数小于corePoolSize,则调用addWorker创建新线程执行任务,成功返回true,失败执行步骤3。
- 如果线程池处于RUNNING状态,则尝试加入阻塞队列,如果加入阻塞队列成功,则尝试进行Double Check,如果加入失败,则执行步骤4。
- 如果线程池变为了非RUNNING状态就需要从阻塞队列中移除队列,并调用reject()方法运行相应的拒绝策略。
- 如果当前线程池为空就新创建一个线程并执行
- 如果第三步判断为非运行状态,尝试新建线程,如果失败则执行拒绝策略。
在步骤2中如果加入阻塞队列成功了,则会进行一个Double Check的过程。Double Check过程的主要目的是判断加入到阻塞队里中的线程是否可以被执行。如果线程池不是RUNNING状态,则调用remove()方法从阻塞队列中删除该任务,然后调用reject()方法处理任务。否则需要确保还有线程执行。
本文来自博客园,作者:LeeJuly,转载请注明原文链接:https://www.cnblogs.com/peterleee/p/10948900.html

浙公网安备 33010602011771号