ThreadPoolExecutor 核心源码逻辑讲解
我这就给你打包一版超清晰又能背的《ThreadPoolExecutor 核心源码逻辑讲解》,简单直接,面试一讲就很能打!
1. execute() 方法内部执行顺序
当你调用 executor.execute(Runnable task) 提交一个任务时,内部流程就是下面这套逻辑:
标准三步走:
- 如果运行的线程数 < corePoolSize,立刻创建新线程执行任务。
- 如果线程数 ≥ corePoolSize,任务加入到任务队列(workQueue)等待执行。
- 如果队列也满了,且线程数 < maximumPoolSize,则创建新线程执行任务。
- 如果线程数已到 maximumPoolSize 且队列也满了,执行拒绝策略(RejectedExecutionHandler)。
对应源码(摘抄核心版,理解即可,不用死记):
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (!isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
2. 为什么是这个顺序?(面试官常问)
答:
这样设计可以最大程度地提高线程利用率,避免频繁地创建和销毁线程,同时还能有效控制内存占用和CPU资源,确保系统稳定性。
更具体地说:
- 优先使用核心线程处理任务 ➔ 快速响应请求
- 任务堆积时利用队列缓冲 ➔ 控制线程数量,避免爆炸增长
- 极端情况下再扩展最大线程数 ➔ 兜底处理高峰请求
- 都扛不住时拒绝新任务 ➔ 保系统稳定,防止雪崩
3. 超快速记忆版口诀
直接送你一个口诀,记下来,回答超快:
✅ 先加核心 ➔ 进队列 ➔ 再扩容 ➔ 最后拒绝
4. 小细节(如果面试官很细问的话)
addWorker(task, true)➔true表示用核心线程addWorker(task, false)➔false表示用最大线程池里的空位ctl是个控制器,记录线程池状态 + 线程数量isRunning()判断线程池是否还在正常运行
(遇到追问,稍微提一点就够了,不需要深入到位运算、AQS 这种底层细节,除非是资深岗位)
总结一版万能说法(面试收尾)
ThreadPoolExecutor 的 execute 方法采用了先用核心线程、再放队列、再扩展最大线程、最后拒绝的策略,兼顾了性能、资源利用率和系统稳定性,是工业界最经典的线程池设计之一。
更多详细内容请关注其他相关文章!