深入理解线程池源码需要拆解其核心组件和工作流程。下面是对其源码关键部分的结构化解析以及线程池(以Java ThreadPoolExecutor
为例)的完整工作流程图和关键步骤说明:
一、整体流程
详细流程说明:
-
任务提交阶段
- execute(Runnable command) 入口
- 优先创建核心线程(
workerCount < corePoolSize
) - 次优尝试任务入队(
workQueue.offer()
) - 队列满时尝试创建非核心线程(
workerCount < maximumPoolSize
) - 所有路径失败时触发拒绝策略
-
线程执行阶段
- runWorker(Worker w) 核心循环
- 先执行初始任务(
firstTask
) - 循环调用 getTask() 获取队列任务
- 执行前后触发钩子函数(
beforeExecute
/afterExecute
) - 加锁保证任务执行原子性(Worker实现AQS锁)
-
任务获取阶段
- getTask() 关键逻辑:
- 判断线程池状态(SHUTDOWN/STOP时返回null)
- 核心线程使用
workQueue.take()
(永久阻塞) - 非核心线程使用
workQueue.poll(keepAliveTime)
(超时等待) - 超时或线程超额时返回null触发回收
-
线程回收阶段
- 非核心线程超时无任务时触发回收
- 线程退出前调用
processWorkerExit()
- 尝试补充线程(避免SHUTDOWN状态无线程处理队列)
- 状态转换至TIDYING时触发
terminated()
钩子
状态流转示意图:
关键设计特点:
动态线程调节
- 核心线程常驻(默认)
- 非核心线程借出机制(超时回收)
- 应急线程创建(队列满时)
3优雅退出机制
- SHUTDOWN模式:消化存量任务
- STOP模式:立即中断+丢弃队列
- TIDYING状态:清理前的最后一站
异常处理流程:
理解此流程可解决:
- 任务堆积诊断(队列选型不当)
- 线程泄漏问题(异常未捕获)
- 资源竞争优化(Worker锁粒度)
- 优雅停机实现(状态机转换)
二、源码解析
核心成员变量
public class ThreadPoolExecutor extends AbstractExecutorService {
// 核心:合并存储线程池状态 (runState) 和工作线程数 (workerCount)
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = 29; // 32位中低29位存线程数
private static final int CAPACITY = (1 << COUNT_BITS) - 1; // 最大线程数 (536870911)
// 线程池状态(高3位存储)
private static final int RUNNING = -1 << COUNT_BITS; // 接受新任务 & 处理队列任务
private static final int SHUTDOWN = 0 << COUNT_BITS; // 不接受新任务,但处理队列任务
private static final int STOP = 1 << COUNT_BITS; // 不接受新任务,不处理队列任务,中断进行中任务
private static final int TIDYING = 2 << COUNT_BITS; // 所有任务终止,workerCount=0,将执行terminated()
private static final int TERMINATED = 3 << COUNT_BITS; // terminated() 执行完成
// 阻塞队列 & 线程工厂
private final BlockingQueue<Runnable> workQueue;
private final ThreadFactory threadFactory;
// 拒绝策略 & 非核心线程存活时间
private volatile RejectedExecutionHandler handler;
private volatile long keepAliveTime;
private volatile int corePoolSize;
private volatile int maximumPoolSize;
// 工作线程集合(需要同步访问)
private final HashSet<Worker> workers = new HashSet<>();
}
核心类:Worker
private final class Worker extends AbstractQueuedSynchronizer implements Runnable {
final Thread thread; // Worker持有的线程
Runnable firstTask; // 初始任务(可为null)
volatile long completedTasks; // 完成任务计数
Worker(Runnable firstTask) {
setState(-1); // 禁止中断,直到runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this); // 将自己作为Runnable传给新线程
}
public void run() {
runWorker(this); // 核心执行逻辑
}
// 实现AQS锁(非重入锁)
protected boolean isHeldExclusively() { ... }
protected boolean tryAcquire(int unused) { ... }
protected boolean tryRelease(int unused) { ... }
}
任务执行流程:execute(Runnable command)
public void execute(Runnable command) {
if (command == null) throw new NullPointerException();
int c = ctl.get();
// 1. 当前线程数 < corePoolSize
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true)) // 创建核心线程执行任务
return;
c = ctl.get(); // 若addWorker失败,重新获取ctl
}
// 2. 线程池运行中且任务入队成功
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); // 确保至少有一个线程处理队列任务
}
// 3. 尝试创建非核心线程执行任务(若失败则拒绝)
else if (!addWorker(command, false))
reject(command);
}
线程执行核心:runWorker(Worker w)
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // 允许中断
boolean completedAbruptly = true;
try {
// 循环获取任务(优先执行firstTask,之后从队列取)
while (task != null || (task = getTask()) != null) {
w.lock(); // 加锁确保任务执行不被中断
// 检查线程池状态(若STOP则确保线程被中断)
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) {
wt.interrupt();
}
try {
beforeExecute(wt, task); // 钩子方法(可重写)
try {
task.run(); // 执行任务
afterExecute(task, null); // 成功钩子
} catch (Throwable ex) {
afterExecute(task, ex); // 异常钩子
throw ex;
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly); // 清理线程退出
}
}
任务获取:getTask()
private Runnable getTask() {
boolean timedOut = false; // 上次poll是否超时?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// 1. 线程池已关闭且队列为空 → 返回null
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
// 2. 判断是否需要淘汰线程(允许核心线程超时 或 wc > corePoolSize)
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
// 3. 两种情况返回null(触发线程回收):
// a) 线程数超过maximumPoolSize
// b) 线程空闲超时(timed && timedOut)
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
// 4. 从队列取任务(超时控制)
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true; // 标记超时
} catch (InterruptedException retry) {
timedOut = false; // 中断重试
}
}
}
拒绝策略(RejectedExecutionHandler)
内置四种策略:
- AbortPolicy(默认):抛出
RejectedExecutionException
- CallerRunsPolicy:调用者线程直接执行任务
- DiscardPolicy:静默丢弃任务
- DiscardOldestPolicy:丢弃队列头任务,重试提交
线程池状态转换
关键设计思想
- 位压缩(ctl):用单变量同时存储状态和线程数,避免竞态条件
- Worker锁:通过AQS实现非重入锁,控制任务执行期间的中断
- 动态线程管理:
getTask()
中的超时机制实现非核心线程回收 - 柔性关闭:
shutdown()
优雅处理队列任务,shutdownNow()
暴力中断
常见问题 & 调优建议
- 线程泄漏:确保任务抛异常时线程能回收(
afterExecute
捕获异常) - 队列选择:
SynchronousQueue
:直接传递(适用于短任务、高吞吐)LinkedBlockingQueue
:无界队列(需警惕OOM)ArrayBlockingQueue
:有界队列(需配合合理拒绝策略)
- 核心参数:
- CPU密集型:
corePoolSize = CPU核数 + 1
- IO密集型:
corePoolSize = 2 * CPU核数
- CPU密集型:
- 监控:重写
beforeExecute
/afterExecute
添加日志/指标统计
理解线程池源码能帮助开发者规避资源耗尽、任务堆积等问题,并根据场景灵活定制线程池行为。