一、線程池執行流程
調用 execute(Runnable command) 提交任務時,處理邏輯如下:
- 若當前線程數 < 核心線程數(
corePoolSize),創建新線程執行任務。
- 若當前線程數 ≥
corePoolSize,任務入隊阻塞隊列(BlockingQueue)。
- 若隊列已滿且線程數 < 最大線程數(
maximumPoolSize),創建新線程執行任務。
- 若隊列滿且線程數達上限,觸發拒絕策略。
二、四種內置拒絕策略
| 策略類 | 行為 |
AbortPolicy | 拋出 RejectedExecutionException(默認) |
DiscardPolicy | 靜默丟棄當前任務 |
DiscardOldestPolicy | 丟棄隊列中最舊任務,嘗試重新提交當前任務 |
CallerRunsPolicy | 由調用線程(提交任務的線程)直接執行任務 |
三、核心源碼解析
1. 狀態與線程數打包
ThreadPoolExecutor 使用 AtomicInteger ctl 將「線程池狀態」(高 3 位)與「工作線程數」(低 29 位)打包存儲:
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3; // 29
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// 狀態常量(高 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;
private static final int TERMINATED = 3 << COUNT_BITS;
2. 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);
} else if (!addWorker(command, false)) {
reject(command);
}
}
3. addWorker() 關鍵步驟
- 雙重檢查線程池狀態與線程數上限。
- 使用 CAS 增加工作線程計數。
- 持有
mainLock 將 Worker 加入 HashSet workers。
- 啟動線程執行任務。
4. Worker 任務執行循環
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();
try {
beforeExecute(wt, task);
task.run();
afterExecute(task, null);
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
四、常用工廠方法創建的線程池
| 方法 | 特點 | 適用場景 |
newFixedThreadPool | 固定大小,核心=最大,隊列無界 | 長期任務、控制並發度 |
newSingleThreadExecutor | 單線程,保證順序執行 | 串行任務 |
newCachedThreadPool | 核心 0,最大無界,空閒 60s 回收 | 大量短期異步任務 |
五、BlockingQueue 核心操作
| 方法 | 行為 |
add(e) | 成功返回 true,失敗拋異常 |
offer(e) | 成功 true,失敗 false(不阻塞) |
put(e) | 阻塞直到入隊成功 |
take() | 阻塞直到取出元素 |
poll(timeout) | 超時返回 null |