Java 线程池(ThreadPoolExecutor)源码分析
一、整体结构
ThreadPoolExecutor
├── 核心参数:corePoolSize、maximumPoolSize、workQueue、keepAliveTime、threadFactory、handler
├── 状态:ctl (AtomicInteger,高3位状态 + 低29位线程数)
├── 工作线程:Worker(继承 AQS,实现 Runnable)
└── 任务队列:BlockingQueue<Runnable>
二、execute():提交任务入口
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);
return;
}
if (!addWorker(command, false))
reject(command);
}
步骤说明
| 步骤 | 逻辑 | 说明 | 原因 |
|---|
| 1 | workerCountOf(c) < corePoolSize | 当前工作线程数小于核心线程数 | 核心线程是常驻的,优先用核心线程执行,减少线程创建开销 |
| 1.1 | addWorker(command, true) | 创建核心线程并执行该任务 | 核心线程不足时立即创建,firstTask 直接交给新线程执行,无需入队 |
| 2 | workQueue.offer(command) | 线程数已满,尝试把任务放入队列 | 核心线程已满时先入队等待,队列有界时可控制背压,避免无限制创建线程 |
| 2.1 | isRunning(recheck) | 再次检查池是否还在运行,防止并发下状态变化 | 入队与取任务存在并发,可能在此期间调用了 shutdown,需 double-check 避免向已关闭池提交 |
| 2.2 | workerCountOf(recheck) == 0 | 若没有工作线程,补一个空任务 Worker,保证队列任务能被消费 | 可能所有 Worker 已退出,但队列还有任务,需补 Worker 否则任务永远无法执行 |
| 3 | addWorker(command, false) | 队列已满,尝试创建非核心线程执行任务 | 队列满说明负载高,临时扩容到 maximumPoolSize 以应对峰值 |
| 4 | reject(command) | 线程数已达 maximumPoolSize,执行拒绝策略 | 池已满,按 RejectedExecutionHandler 策略处理(抛异常、丢弃、调用者执行等) |
三、addWorker():添加工作线程
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
if (rs >= SHUTDOWN && !(rs == SHUTDOWN && firstTask == null && !workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get();
if (runStateOf(c) != rs)
continue retry;
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive())
throw new IllegalThreadStateException();
workers.add(w);
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
步骤说明
| 步骤 | 逻辑 | 说明 | 原因 |
|---|
| 1 | rs >= SHUTDOWN 判断 | 若已 SHUTDOWN/STOP/TIDYING/TERMINATED,一般不再接受新任务 | 关闭后不应再创建新 Worker,避免资源浪费和状态混乱 |
| 1.1 | 特殊:SHUTDOWN && firstTask==null && !workQueue.isEmpty() | 允许添加「空任务」Worker 去消费队列剩余任务 | shutdown 后不再接新任务,但需把队列中已有任务执行完,空 Worker 会通过 getTask 取队列任务 |
| 2 | wc >= corePoolSize 或 maximumPoolSize | 核心/非核心线程数已达上限,不再创建 | 防止超过配置的线程数,保证资源可控 |
| 2.1 | compareAndIncrementWorkerCount(c) | CAS 增加工作线程计数,避免并发超限 | 多线程并发 execute 时,CAS 保证 workerCount 准确,防止超卖 |
| 3 | new Worker(firstTask)、workers.add(w) | 创建 Worker,加入 workers 集合 | Worker 封装线程与任务,workers 用于 shutdown 时遍历中断 |
| 4 | t.start() | 启动 Worker 内部线程,进入 runWorker() | 线程启动后进入循环取任务、执行任务的流程 |
四、Worker:工作线程封装
private final class Worker extends AbstractQueuedSynchronizer implements Runnable {
final Thread thread;
Runnable firstTask;
Worker(Runnable firstTask) {
setState(-1);
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
public void run() {
runWorker(this);
}
}
步骤说明
| 步骤 | 逻辑 | 说明 | 原因 |
|---|
| 1 | setState(-1) | 初始 AQS 状态为 -1 | 防止 Worker 刚创建时被误判为可中断,runWorker 中 unlock 后才允许中断 |
| 2 | getThreadFactory().newThread(this) | 用线程工厂创建线程,this 作为 Runnable | 统一线程创建方式,Worker 的 run 会调用 runWorker,形成执行入口 |
| 3 | 继承 AQS | 实现简单锁 | 区分空闲(lock 前)与工作中(lock 后),shutdown 时只中断空闲 Worker,避免打断正在执行的任务 |
五、runWorker():工作线程主循环
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock();
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
try {
task.run();
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
步骤说明
| 步骤 | 逻辑 | 说明 | 原因 |
|---|
| 1 | task = w.firstTask 或 getTask() | 优先执行创建时传入的 firstTask,之后从队列取任务 | firstTask 是 addWorker 时传入的,直接执行可少一次入队出队;之后从队列取任务实现复用 |
| 2 | 状态检查 + 中断 | 若池已 STOP 或当前线程被中断,确保线程被中断,以便快速退出 | STOP 时要尽快结束,中断可让阻塞在 getTask 的线程及时退出 |
| 3 | task.run() | 直接执行任务(不是 start(),复用当前线程) | Worker 线程就是工作线程,直接 run 在当前线程执行,无需再起新线程 |
| 4 | processWorkerExit() | 线程退出时:减少 worker 计数、必要时补充新 Worker、尝试终止线程池 | 保证 workerCount 正确,SHUTDOWN 时若队列非空可补 Worker,最终尝试转为 TERMINATED |
六、getTask():从队列取任务
private Runnable getTask() {
boolean timedOut = false;
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount(c);
return null;
}
int wc = workerCountOf(c);
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
步骤说明
| 步骤 | 逻辑 | 说明 | 原因 |
|---|
| 1 | rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty()) | 池已关闭,且要么已 STOP,要么队列已空,不再取任务 | STOP 时不处理队列;SHUTDOWN 时队列空才退出,保证队列任务被消费完 |
| 2 | timed = allowCoreThreadTimeOut || wc > corePoolSize | 超过核心数的线程或允许核心超时时,使用超时取任务 | 非核心线程空闲超过 keepAliveTime 应回收;核心线程在 allowCoreThreadTimeOut 时也可回收 |
| 2.1 | wc > maximumPoolSize 或 (timed && timedOut) | 线程数超限或上次取任务超时,且满足回收条件时,减少 worker 并返回 null | 扩容后负载下降需缩容;超时取到 null 表示空闲过久,可回收以释放资源 |
| 3 | poll(keepAliveTime) / take() | 超时取或阻塞取,超时返回 null 会触发 timedOut = true,下次循环可能回收线程 | 核心线程用 take 永久阻塞保持存活;非核心用 poll 超时,超时后 timedOut 为 true 可能触发回收 |
七、整体执行流程
execute(task)
│
├─ 线程数 < corePoolSize ──→ addWorker(task, true) ──→ 新建核心线程执行
│
├─ 线程数 ≥ corePoolSize
│ │
│ ├─ workQueue.offer(task) 成功 ──→ 任务入队
│ │ │
│ │ └─ workerCount == 0 ──→ addWorker(null, false) 补一个空 Worker
│ │
│ └─ 队列满 ──→ addWorker(task, false) ──→ 新建非核心线程执行
│ │
│ └─ 失败 ──→ reject(task)
│
└─ Worker 启动 ──→ runWorker()
│
├─ 执行 firstTask
│
└─ 循环 getTask()
│
├─ take() / poll() 取到任务 ──→ task.run()
│
└─ 返回 null(超时或池关闭)──→ processWorkerExit()
八、状态与 ctl
RUNNING = -1 << 29
SHUTDOWN = 0 << 29
STOP = 1 << 29
TIDYING = 2 << 29
TERMINATED = 3 << 29
九、小结
| 环节 | 作用 |
|---|
| execute() | 决定:新建核心线程 / 入队 / 新建非核心线程 / 拒绝 |
| addWorker() | 创建 Worker、加入 workers、启动线程 |
| Worker | 封装线程和 firstTask,实现 Runnable |
| runWorker() | 循环取任务并执行,退出时调用 processWorkerExit |
| getTask() | 从队列取任务,控制超时回收和池关闭时的退出 |