线程池ThreadPoolExecutor源码跟踪
execute(Runnable command)
public void execute(Runnable command) {
// 不允许提交null
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
// 获取工作线程总数,判断如果小于核心线程数,则启动一个核心线程去执行任务,如果大于等于核心线程数,或启动新线程失败,则进入下面的判断
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// todo CachedThreadPoolExecutor在最开始的时候这里的怎么过掉的?
// 疑问点在于,Cache线程池刚启动时,核心线程数为0,那么上面那个if判断会直接过掉,而它的工作队列是SynchronousQueue,没有工作线程的情况下offer()应该会一直阻塞在那里,这不就陷入了死循环??
// 如果线程池状态正常,且往工作队列中添加任务成功,则进行二次校验,防止线程池状态在这之间变化
if (isRunning(c) && workQueue.offer(command)) {
// 检查线程池状态,如果线程池状态异常,则我们需要移除刚才添加到工作队列中的任务
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
// 线程池状态异常,且移除任务成功,对该任务执行拒绝策略
reject(command);
// 反之,如果线程池状态正常,或线程池状态异常,但是移除任务失败,则再判断工作线程数,如果为0,则启动一个新线程
// 对于前者,状态正常,但是工作线程数为0,那么启动一个新线程很正常
// 对于后者,线程池状态异常,从工作队列中移除任务失败,但是判断线程池中线程数量为0,此时再启动一个新线程来执行任务,应该是一个无奈之举,毕竟移除任务失败了
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 如果线程池状态异常,或线程状态正常,但是往工作队列中添加任务失败,那么启动一个新工作线程来执行直接任务,并在启动失败时执行拒绝策略
// 对于这两种情况,addWorker()中都会根据线程池状态判断应该返回的结果
else if (!addWorker(command, false))
reject(command);
addWorker(Runnable firstTask, boolean core)
private boolean addWorker(Runnable firstTask, boolean core) {
// 定义一个retry循环
retry:
for (;;) {
// 获取当前线程池状态
int c = ctl.get();
int rs = runStateOf(c);
// 如果线程池状态大于等于SHUTDOWN,且不等于SHUTDOWN时(TIDYING/STOP/TERMINATED),工作队列为空,firstTask不为空,则直接返回false,告知增加worker失败
// 这里是为了应对execute()方法中的两种情况,一种是线程池状态为SHUTDOWN,但是工作队列中被添加了任务且移除失败,此时没办法必须启动一个新线程把任务执行掉,传入的firstTask为null
// 第二种情况是线程池状态异常,那么在非SHUTDOWN、且任务不为空、工作队列为空的情况下,直接返回false,告知调用方添加线程失败
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
// 该层循环的作用是计算线程数,确认能增加并增加
for (;;) {
// 获取当前线程数量
int wc = workerCountOf(c);
// CAPACITY是线程池可允许的线程最大数量,如果大于该值,或核心线程/最大线程已达到,则返回false,告知无法新增新线程
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
// 采用cas对线程数量进行增加,如果成功即可中断当前retry循环
if (compareAndIncrementWorkerCount(c))
break retry;
// 使用cas增加线程数量失败,判断线程池状态是否和retry循环开始时的线程池状态相同,相同的话则继续retry的内循环,不同的话中断内循环,继续外循环
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
// 到这里说明线程数量workCount已经增加完毕,需要进行真正的创建线程动作了
// 定义两个布尔值,分别代表新增的线程已启动和已创建
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
// 包装传入的Runnable,Worker中会存储有一个工作线程Thread,和传入的任务内容Runnable,工作线程会直接调用任务内容的run()
w = new Worker(firstTask);
final Thread t = w.thread;
// 如果线程为空,说明ThreadFactory出问题了,if中的代码也不需要执行
if (t != null) {
// 获取线程池的可重入锁,并加锁
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
// 如果当前线程池状态为RUNNING,或为SHUTDOWN,且firstTask为空,则继续以下的逻辑
// 线程池状态为SHUTDOWN,且firstTask为空,意味着当前方法只是为了启动一个新的工作线程
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
// 如果线程状态是alive,说明线程的start()已经被调用,抛出线程状态异常
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
// 添加到工作线程集合中
workers.add(w);
// 判断当前工作线程数量,并赋值该largestPoolSize,该变量的作用是追踪当前线程池的最大线程数量
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
// 更新workerAdded变量,代表工作线程已经被添加到线程池中
workerAdded = true;
}
} finally {
mainLock.unlock();
}
// 如果工作线程已经被添加到线程池中,那么就启动工作线程中的执行线程,并更新workerStarted为true,代表工作线程已经被启动
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
// 如果因为某些原因工作线程启动失败,会调用addWorkerFailed(),该方法主要做三件事,从线程池中移除这个启动失败的线程,减少线程数量,并调用tryTerminated()方法尝试终止线程池
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
shutdown()
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 校验当前线程是否有关闭线程的权限,并检查当前线程对每个工作线程是否有权限操作
checkShutdownAccess();
// 采用cas方法更新线程池状态
advanceRunState(SHUTDOWN);
// 中断空闲的工作线程
interruptIdleWorkers();
// shutdown的钩子方法,ThreadPoolExecutor没有使用该方法,ScheduledThreadPoolExecutor会使用该方法情况workQueue
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
// 尝试更新线程池状态为TERMINATED
tryTerminate();
}
shutdownNow()
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
// 加锁操作
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 校验当前线程是否有关闭线程的权限,并检查当前线程对每个工作线程是否有权限操作
checkShutdownAccess();
// 采用cas方法更新线程池状态
advanceRunState(STOP);
// 直接中断所有started的且未interrupt的工作线程
interruptWorkers();
// 将剩余的任务返回,并清空workQueue
tasks = drainQueue();
} finally {
mainLock.unlock();
}
// 尝试更新线程池状态为TERMINATED
tryTerminate();
return tasks;
}
tryTerminate()
final void tryTerminate() {
for (;;) {
// 获取状态
int c = ctl.get();
// 判断线程池状态是RUNNING,或线程池状态是TIDYING或TERMINATED,或当前线程池状态为SHUTDOWNS时工作队列不为空
// 第一种情况线程池无法关闭,第二种情况下线程池会直接调用terminated()方法终止线程,不需要tryTerminate(),第三种情况下需先等待任务队列全部执行完
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
// 如果当前工作线程数不为0,则中断一个空闲的工作线程以传播shutdown信号
// todo 后半句没懂,传播shutdown信号?做什么?方法中只是单纯的中断了一个工作线程,没有做其它任何事
// 这里中断的是空闲的工作线程,会导致runWorker()中抛出interrupt异常,然后进入processWorkerExit(),然后再次调用tryTerminate(),
// 不断循环直到workCount一直为0?这种传播?
if (workerCountOf(c) != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 设置当前线程池状态为TIDYING
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
// 线程终止方法,在ThreadPoolExecutor只是个空方法
terminated();
} finally {
// 线程池已终止,设置线程池状态为TERMINATED,并通过Condition通知所有的awaitTermination()方法
ctl.set(ctlOf(TERMINATED, 0));
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
runWorker(Worker w)
final void runWorker(Worker w) {
// 获取当前线程
Thread wt = Thread.currentThread();
// 获取工作线程内已有的firstTask,并将工作线程的firstTask置空
Runnable task = w.firstTask;
w.firstTask = null;
// 在实际开始执行任务前解锁当前worker,允许在这段时间内中断worker
w.unlock(); // allow interrupts
// 用于标记当前线程是否完全中断
boolean completedAbruptly = true;
try {
// 当task不为空或getTask()可以获取到任务时,执行while循环
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
// 判断线程池状态,如果{线程池状态为STOP后 或 {当前线程中断且线程池已关闭且且线程池状态为STOP后}} 且线程中断后没有再中断,则中断当前线程
// todo 想知道这些判断都是针对什么情况的...
if ((
runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))
)
&& !wt.isInterrupted())
wt.interrupt();
try {
// 执行前置钩子方法
beforeExecute(wt, task);
Throwable thrown = null;
// 直接运行task的run(),然后捕获异常,将Throwable的异常包装成Error,所有异常捕获后赋值给thrown后再抛出,
// 抛出的部分由uncaughtExceptionHandler处理,thrown用于afterExecute处理
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
// 执行后置钩子方法
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
// 线程因为某些自身原因终止(一般是被线程池interrupt),需要执行工作线程退出的一些流程,其中会调用tryTerminate终止线程池
// completedAbruptly:代表线程是否突然中断,或者是任务已执行完且队列已清空
processWorkerExit(w, completedAbruptly);
}
}
processWorkerExit(Worker w, boolean completedAbruptly)
private void processWorkerExit(Worker w, boolean completedAbruptly) {
// 如果工作线程是突然中断的,那么需要减少一个工作线程数量
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount();
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 将工作线程的完成任务数加到completeTaskCount,该变量的作用是记录当前线程池完成的任务总数
completedTaskCount += w.completedTasks;
// 从工作线程集合中移除任务
workers.remove(w);
} finally {
mainLock.unlock();
}
// 尝试终止线程池,如果是工作线程的正常关闭,那么该方法会因为线程池状态的不符合直接返回
tryTerminate();
// 判断线程池状态是否在STOP之前,即RUNNING或SHUTDOWN
int c = ctl.get();
if (runStateLessThan(c, STOP)) {
// 如果工作线程是正常结束的话
if (!completedAbruptly) {
// 判断最少工作线程数应该是多少
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
// 如果最少工作线程数为0,且任务队列不为空,说明最少需要一个线程来执行任务队列中的任务
if (min == 0 && ! workQueue.isEmpty())
min = 1;
// 如果当前工作线程数大于等于最少线程数,那么说明工作线程数已经够了,直接返回即可
if (workerCountOf(c) >= min)
return; // replacement not needed
}
// 如果工作线程是非正常结束,或正常结束但是当前工作线程数小于最少工作线程数,那么就需要启动一个工作线程,来执行任务
addWorker(null, false);
}