線程池是 Java 並發編程的核心基礎設施,統一管理線程生命週期、任務隊列與執行策略。本文深度解析 ThreadPoolExecutor 核心參數、執行流程、源碼關鍵邏輯(Worker、工作隊列、拒絕策略),並提供生產級配置建議與監控方案。
Executor (頂層接口)
└─ ExecutorService
├─ AbstractExecutorService (模板方法)
│ └─ ThreadPoolExecutor (核心實現)
├─ ScheduledExecutorService
│ └─ ScheduledThreadPoolExecutor
└─ ForkJoinPool (分治任務專用)
Executors (工廠類) → 提供預設配置的靜態工廠方法
public ThreadPoolExecutor(
int corePoolSize, // 核心線程數(常駐)
int maximumPoolSize, // 最大線程數(含非核心)
long keepAliveTime, // 非核心線程閒置存活時間
TimeUnit unit, // 時間單位
BlockingQueue workQueue, // 任務隊列
ThreadFactory threadFactory, // 線程創建工廠
RejectedExecutionHandler handler // 拒絕策略
)
| 參數 | CPU 密集型 | IO 密集型 | 說明 |
|---|---|---|---|
| corePoolSize | CPU 核心數 + 1 | 2 * CPU 核心數 | 核心線程常駐不回收(除非 allowCoreThreadTimeOut=true) |
| maximumPoolSize | corePoolSize | corePoolSize * 2 | 突發流量緩衝,視隊列長度決定 |
| workQueue | ArrayBlockingQueue(有界) | LinkedBlockingQueue(無界) 或 SynchronousQueue | 有界隊列防 OOM,無界需配合 maxPoolSize |
| keepAliveTime | 60s | 60-300s | 非核心線程閒置回收時間 |
| threadFactory | 自定義命名 | 自定義命名 | 便於日誌追蹤、監控(如 "order-process-%d") |
| handler | CallerRunsPolicy | CallerRunsPolicy | 削峰填谷,由調用者執行任務 |
| 方法 | 實際配置 | 缺陷 | 建議 |
|---|---|---|---|
| newFixedThreadPool(n) | core=n, max=n, LinkedBlockingQueue(無界) | 隊列無界 → 任務積壓 OOM | ❌ 禁用,改用有界隊列自定義 |
| newSingleThreadExecutor() | core=1, max=1, LinkedBlockingQueue(無界) | 同無界風險 | ❌ 禁用 |
| newCachedThreadPool() | core=0, max=Integer.MAX, SynchronousQueue | 線程無上限 → 突發流量創建過多線程 OOM | ❌ 禁用 |
| newScheduledThreadPool(n) | core=n, max=Integer.MAX, DelayedWorkQueue | 非核心線程無上限 | ⚠️ 僅定時任務用,注意 maxPoolSize |
阿里巴巴開發手冊強制規定:不允許使用 Executors 預設工廠,必須自定義 ThreadPoolExecutor。
submit(task)
│
▼
corePoolSize 已滿?
├─ 否 → 創建核心線程執行 → 完成
│
└─ 是 → 嘗試入隊 (workQueue.offer)
│
├─ 成功 → 等待核心線程拉取執行
│
└─ 失敗 (隊列滿) → maximumPoolSize 已滿?
├─ 否 → 創建非核心線程執行
│
└─ 是 → 執行拒絕策略 (handler.rejectedExecution)
// 簡化版 Worker.runWorker()
final void runWorker(Worker w) {
Runnable task = w.firstTask;
w.firstTask = null;
// 關鍵:while 循環持續從隊列獲取任務
while (task != null || (task = getTask()) != null) {
w.lock(); // 可重入鎖,控制線程狀態
try {
beforeExecute(w.thread, task);
task.run(); // 執行用戶任務
afterExecute(task, null);
} catch (RuntimeException x) {
// 異常處理
} finally {
w.unlock();
task = null;
}
}
// 退出循環 → 線程結束 → 線程池回收 Worker
processWorkerExit(w, completedAbruptly);
}
// getTask() 核心邏輯
private Runnable getTask() {
boolean timed = allowCoreThreadTimeOut || workerCount > corePoolSize;
for (;;) {
// timed=true 使用 poll(keepAliveTime),超時返回 null 觸發線程回收
// timed=false 使用 take() 永久阻塞
Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)
: workQueue.take();
if (r != null) return r;
// 隊列空且超時 → 返回 null → Worker 退出
if (workerCount > corePoolSize || allowCoreThreadTimeOut) return null;
}
}
核心洞察:
while (task = getTask()) 循環,而非線程結束後重建。allowCoreThreadTimeOut=true 可讓核心線程也超時回收,適合間歇性負載。workQueue.take() 阻塞等待,poll(timeout) 超時返回 null 觸發縮容。| 隊列 | 特性 | 適用場景 | 風險 |
|---|---|---|---|
| ArrayBlockingQueue | 有界陣列、FIFO | 固定緩衝、背壓控制 | 需預估容量 |
| LinkedBlockingQueue | 無界鏈表、FIFO | 任務量可控、內存充裕 | ⚠️ 無界易 OOM |
| SynchronousQueue | 無容量、直接移交 | CachedThreadPool、高吞吐低延遲 | 無緩衝,任務必須立即執行 |
| PriorityBlockingQueue | 優先級堆 | 任務有優先級 | 非 FIFO,需實現 Comparable |
| DelayedWorkQueue | 延遲隊列(堆) | ScheduledThreadPool | 專用 |
RejectedExecutionException,調用者需捕獲。自定義策略:實現 RejectedExecutionHandler,可記錄日誌、持久化到資料庫、發送告警、轉發到備用隊列。
ThreadPoolExecutor executor = ...;
// 即時指標
int active = executor.getActiveCount(); // 正在執行任務的線程數
int poolSize = executor.getPoolSize(); // 當前線程池大小
int coreSize = executor.getCorePoolSize(); // 核心線程數
int maxSize = executor.getMaximumPoolSize(); // 最大線程數
long completed = executor.getCompletedTaskCount(); // 已完成任務數
long queued = executor.getQueue().size(); // 隊列積壓數
long total = executor.getTaskCount(); // 總提交任務數
// 衍生指標
double queueUtilization = (double) queued / queueCapacity;
double threadUtilization = (double) active / poolSize;
double rejectionRate = rejectedCount / total;
接入 Prometheus/Grafana 監控:active、queued、rejectionRate 設定告警閾值。
// 1. 停止接受新任務,處理完隊列任務
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
// 2. 強制關閉,取消未執行任務,中斷執行中任務
List remaining = executor.shutdownNow();
// 記錄剩餘任務,決定是否持久化重試
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
log.error("線程池未能在限定時間內關閉");
}
}
} catch (InterruptedException ex) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
@Configuration
@EnableAsync
public class ThreadPoolConfig {
@Bean("businessExecutor")
public ThreadPoolTaskExecutor businessExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200); // 有界隊列
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("biz-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true); // 優雅關閉
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
}
// 使用
@Async("businessExecutor")
public CompletableFuture processOrder(Order order) { ... }
ThreadPoolExecutor。ArrayBlockingQueue) + **CallerRunsPolicy** 防禦流量洪峰。business-module-%d,便於 Arthas/jstack 排查。shutdown() → awaitTermination → shutdownNow()。Thread.setDefaultUncaughtExceptionHandler 或 Spring AsyncUncaughtExceptionHandler。