一、ThreadPoolExecutor中的核心变量和内部类
1.1 ctl
线程池内部使用ctl来维护线程状态(runState)和线程数量(workerCount),高三位表示线程线程状态(runState),低29位表示线程数量(workerCount)
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
1.2 内部类Worker
Worker是线程池中为了维护线程的状态并维护线程的生命周期而设计的。
这worker类实现了Runnable接口,并持有一个线程和一个初始化任务。
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
private static final long serialVersionUID = 6138294804551838833L;
// worker持有的线程,可以为空
final Thread thread;
//初始化任务
Runnable firstTask;
/*省略*/
}
二、execute()分析
所有的任务调度都由有execute()进行完成的。主要有三部分
- 判断当前的工作线程数是否小于核心线程数
- 判断线程池是否为Running状态并且可以加入到缓存队列中
- 判断是否可用尝试添加一个新的线程
详细分析
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
// 获取ctl值(包括了线程状态和线程数量)
int c = ctl.get();
// workerCountOf(): 根据clt获取线程数量
// 判断当前线程数是否小于核心线程数
if (workerCountOf(c) < corePoolSize) {
/**
* addWorker(): 尝试增加核心线程或者非核心线程以执行任务(区分core)
* @param firstTask 表示线程启动后第一个执行的任务
* @param core 判断新添加的线程是否应该被视为核心线程(true)还是非核心线程(false)。
*/
if (addWorker(command, true))
return;
// 再次获取值
c = ctl.get();
}
// 如果当前的线程池还在运行并且加入缓存队列成功
if (isRunning(c) && workQueue.offer(command)) {
// 获取clt
int recheck = ctl.get();
// 如果线程池状态不是运行状态就从队列移除任务并拒绝执行
if (! isRunning(recheck) && remove(command))
reject(command);
// 如果活跃的线程为空时
else if (workerCountOf(recheck) == 0)
// 尝试添加一个非核心线程来检查队列
addWorker(null, false);
}
//如果不能直接执行也不能入队,尝试添加非核心线程执行任务,失败则拒绝任务
else if (!addWorker(command, false))
reject(command);
}
其执行流程如下图所示: