ThreadPoolExecutor源码解读(三)——如何优雅的关闭线程池(shutdown、shutdownNow、awaitTermination)
在面试前我整理归纳了一些面试学习资料,文中结合我的朋友同学面试美团滴滴这类大厂的资料及案例由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!大家看完有什么不懂的可以在下方留言讨论也可以关注。《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!些面试学习资料,文中结合我的朋友同学面试美团
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
2、为什么要调用tryTerminate()?
tryTerminate()不会强行终止线程池,当workerCount为0,workerQueue为空时:
-
状态流转到
TIDYING。 -
然后调用钩子函数
terminated()。 -
状态从
TIDYING流转到TERMINATED。 -
调用
termination.sinaglAll(),通知前面阻塞在awaitTermination的所有调用者线程。
final void tryTerminate() {
for (;😉 {
int c = ctl.get();
if (isRunning© ||
runStateAtLeast(c, TIDYING) ||
(runStateOf© == SHUTDOWN && ! workQueue.isEmpty()))
return;
if (workerCountOf© != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
return;
}
//1.当workQueue为空,workerCount为空时,cas流转状态为TIDYING
//2.并调用了一个空钩子函数terminated
//3.最终将状态流转为TERMINATED,并通知awaitTermination
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
terminated();
} finally {
ctl.set(ctlOf(TERMINATED, 0));
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS 自旋
}
}
3、termination.signalAll()唤醒的是什么?
awaitTermination()逻辑很简单,就是重复判断runState是否到达最终状态TERMINATED,如果是直接返回true,如果不是,调用termination.awaitNanos(nanos)阻塞一段时间,苏醒后再判断一次,如果runState是TERMINATED返回true,否则返回false。
/**
- Wait condition to support awaitTermination
*/
private final Condition termination = mainLock.newCondition();
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (;😉 {
判断当前的runstate是否大于等于TERMINATED
if (runStateAtLeast(ctl.get(), TERMINATED))
return true;
if (nanos <= 0)
return false;
//如果不是TERMINATED,将等待nanos
nanos = termination.awaitNanos(nanos);
}
} finally {
mainLock.unlock();
}
}
三、shutdownNow()将runState流转为STOP
shutdownNow()和shutdown()相似,主要做了5步:
-
检查是否有中断线程池权限。
-
设置
runStatus为STOP。 -
中断所有工作线程。
-
清空工作队列。
-
尝试终止线程池。
public List shutdownNow() {
List tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//1.检查是否有shutdown权限
checkShutdownAccess();
//2.设置runStatus为stop
advanceRunState(STOP);
//3.给worders发送终止信号
interruptWorkers();
//4.清空阻塞队列
tasks = drainQueue();
} finally {
mainLock.unlock();
}
//5.尝试终止线程池
tryTerminate();
return tasks;
}
shutdownNow()和shutdown()不同之处在于:
-
shutdownNow()会终止所有工作线程,不管是空闲还是正在运行。 -
shutdownNow()会清空阻塞队列。
private void interruptWorkers() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
w.interruptIfStarted();
} finally {
mainLock.unlock();
}
}
private List drainQueue() {
BlockingQueue q = workQueue;
ArrayList taskList = new ArrayList();
//删除所有元素并加入到taskList
q.drainTo(taskList);
if (!q.isEmpty()) {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。


既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后
在面试前我整理归纳了一些面试学习资料,文中结合我的朋友同学面试美团滴滴这类大厂的资料及案例

由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
大家看完有什么不懂的可以在下方留言讨论也可以关注。
觉得文章对你有帮助的话记得关注我点个赞支持一下!
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!
些面试学习资料,文中结合我的朋友同学面试美团滴滴这类大厂的资料及案例
[外链图片转存中…(img-0jZRIYvh-1711863103041)]
[外链图片转存中…(img-4oHjt8VH-1711863103042)]
由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
大家看完有什么不懂的可以在下方留言讨论也可以关注。
觉得文章对你有帮助的话记得关注我点个赞支持一下!
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!
更多推荐




所有评论(0)