// 提交执行任务
// command 就是提交过来的任务
public void execute(Runnable command) {
// 提交的任务不能为null 健壮性判断
if (command == null)
throw new NullPointerException();
// 获取核心属性ctl值,用于后续判断
int c = ctl.get();
// 如果工作线程个数小于核心线程数
// 满足要求,添加核心工作线程
if (workerCountOf(c) < corePoolSize) {
// addWorker(任务,是否是核心线程) ture: 核心线程,false:非核心线程
// addWorker返回true: 代表添加工作线程成功
// addWorker返回false: 代表添加工作线程失败
// addWorker中会基于线程池状态,以及工作线程个数判断,查看能否添加工作线程
if (addWorker(command, true))
// 工作线程构建出来了,任务也交给command去处理了
return;
// 说明线程池状态或者是工作线程个数发生了变化,导致添加失败,需要重新获取ctl值
c = ctl.get();
}
// 添加核心工作线程失败后
// 先判断线程池状态是否是RUNNING状态,如果是正常基于阻塞队列的offer方法,将任务添加到阻塞队列
if (isRunning(c) && workQueue.offer(command)) {
// 如果任务添加到阻塞队列成功,走if内部
// 如果任务在丢到阻塞队列之前,线程池状态发生改变了
// 重新获取ctl
int recheck = ctl.get();
// 如果线程池的状态不是RUNNING状态,将任务从阻塞队列中移除
if (! isRunning(recheck) && remove(command))
// 并且直接拒绝策略
reject(command);
// 在这,说明阻塞队列有我刚放进去的任务
// 查看一下工作线程数是不是0个
// 如果工作线程为0个,需要添加一个非核心工作线程去处理阻塞队列中的任务
// 发生这种情况有两种:
// 1. 构建线程池时,核心线程数可以是0个
// 2. 即使有核心线程,可以设置核心线程也允许超时,设置allowCoreThreadTimeOut(默认false)为ture
else if (workerCountOf(recheck) == 0)
// 为了避免阻塞队列中的任务堆积,添加一个非核心线程去处理
addWorker(null, false);
}
// 任务添加到阻塞队列失败
// 构建一个非核心工作线程
// 如果添加非核心工作线程成功,直接完成
else if (!addWorker(command, false))
// 添加失败,执行拒绝策略
reject(command);
}
// 校验和添加启动工作线程
private boolean addWorker(Runnable firstTask, boolean core) {
// =======================第一块====================
// 外层for循环在校验线程池的状态
// 内层for循环是在校验工作线程的个数
// retry是给外层for循环添加的一个标记,为了方便在内层for循环跳出到外层for循环
retry:
for (;;) {
// 获取ctl
int c = ctl.get();
// 拿到ctl的高3位的值
int rs = runStateOf(c);
// =====================线程池状态判断==========================
// 如果线程池状态是SHUTDOWN,并且此时阻塞队列有任务,工作线程为0,则添加一个工作线程去处理阻塞队列的任务