用于关闭线程池的方法之一。简单来说,会等任务都完成后在关闭线程池。
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock(); //全局锁
try {
//查看调用shutdown的线程是否有权限结束线程池中的worker线程
checkShutdownAccess();
//变更标志位
advanceRunState(SHUTDOWN);
//此方法会调用interruptIdleWorkers方法,尝试中断所有线程。
//但任务队列不空,worker不会被关闭。
interruptIdleWorkers();
onShutdown(); //空实现方法
} finally {
mainLock.unlock();
}
tryTerminate(); //尝试结束线程池
}
保证不会发生状态退化,且使用cas保证一致性
private void advanceRunState(int targetState) {
for (;;) {
int c = ctl.get();
if (runStateAtLeast(c, targetState) ||
ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
break;
}
}
shutdown调用,对每个worker进行判定,只有当worker不再执行任务了,才会将其中断
参数onlyOne判断是否只关闭一个worker
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
//worker中有aqs不可重入锁,保证只有worker在获取任务时,才能trylock成功,才会尝试杀死worker线程;
//t.isInterrupted保证线程尚未被中断
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
shutdownNow将标志位ctl置为stop,并清空队列
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP); //变更标志位
interruptWorkers(); //中断所有worker
tasks = drainQueue(); //获取任务队列中的任务
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
shutdownNow调用的方法,无论任务队列是否有任务,无论worker是否正在执行任务,都会尝试关闭线程。
private void interruptWorkers() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
//无论worker是否加锁都会被中断,除非worker未开始执行任务(状态为-1)
w.interruptIfStarted();
} finally {
mainLock.unlock();
}
}
此方法会将stop或者shutdown(并且队列已空)状态的线程池 转变为tidying状态。shutdown和shutdownNow等多个删除或关闭worker的方法会调用此方法。
final void tryTerminate() {
for (;;) {
int c = ctl.get();
//三种情况下,不去执行。
//1 状态为running,既运行时
//2 状态为tidying和terminated线程池中已经没有worker,不需要执行
//3 状态为shutdown,但队列中还有任务未执行,不能执行
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
//尝试中断一个空闲线程,并返回。
//当shutdown方法被调用,worker消耗完任务后,会由于阻塞抛出异常后返回,结束runworker方法,最后调用此tryTerminate方法,关闭一个空闲线程。
if (workerCountOf(c) != 0) {
interruptIdleWorkers(ONLY_ONE);
return;
}
//线程池中worker已经全部关闭
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) { //cas变更状态为tidying
try {
terminated(); //空方法
} finally {
ctl.set(ctlOf(TERMINATED, 0)); //变为terminated
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
很多方法都会调用这个方法。作用是尝试关闭一个worker线程,或者当线程都被关闭是将线程池状态变为terminated。若此方法cas改变线程池状态失败,则会再次循环,再次使用cas对线程池状态进行改变。
至此ThreadPoolExecutor主要方法都被分析完毕,附上另外两篇文章:
https://blog.csdn.net/xiaoyuchenCSDN/article/details/83549068
https://blog.csdn.net/xiaoyuchenCSDN/article/details/83615323