面试官: 有了解过线程池的工作原理吗?说说看
前言
目前正在出一个Java多线程专题长期系列教程,从入门到进阶含源码解读, 篇幅会较多, 喜欢的话,给个关注❤️ ~
本节主要带大家从ThreadPoolExecutor源码角度来了解一下线程池的工作原理,一起来看下吧~
Executor 接口
首先Executor这个接口是线程池实现的顶层接口类,我们上节遇到的ExecutorService也是继承了Executor
public void execute(Runnable command) {
// 如果任务不存在 抛空异常
if (command == null)
throw new NullPointerException();
// 获取当前状态值
int c = ctl.get();
// 当前线程数小于corePoolSize,则调用addWorker创建核心线程执行任务
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// 如果不小于corePoolSize,则将任务添加到workQueue队列。
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
// 如果isRunning返回false(状态检查),则remove这个任务,然后执行拒绝策略。
if (! isRunning(recheck) && remove(command))
reject(command);
// 线程池处于running状态,但是没有线程,则创建线程
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 如果放入workQueue失败,则创建非核心线程执行任务,
else if (!addWorker(command, false))
// 如果这时创建失败,就会执行拒绝策略。
reject(command);
}
在源码中,我们可以看到,多次进行了isRunning判断。在多线程的环境下,线程池的状态是多变的。很有可能刚获取线程池状态后线程池状态就改变了
总结
下面给大家简要的总结一下线程池的处理流程
-
线程总数量小于线程池中保留的线程数量(corePoolSize),无论线程是否空闲,都会新建一个核心线程执行任务,这一步需要获取
全局锁 -
线程总数量大于corePoolSize时,新来的线程任务会进入任务队列中等待,然后空闲的核心线程会依次去缓存队列中取任务来执行,从而达到线程的复用
-
当缓存队列满了,会创建非核心线程去执行这个任务。
-
缓存队列满了, 且总线程数达到了maximumPoolSize,则会采取拒绝策略进行处理。
结束语
它的源码还是比较长的,一篇文章说不清楚,有兴趣的同学可以通过本篇文章的理解继续阅读它的源码。
下一节, 继续带大家详探讨ThreadPoolExecutor中是如何进行线程复用
本篇文章来源于微信公众号: 程序员皮卡秋
微信扫描下方的二维码阅读本文

Comments NOTHING