JDK 1.5 引入 java.util.concurrent 包,ThreadPoolExecutor 成為 Java 併發編程的基石。它不僅解決了「頻繁創建/銷毀線程開銷大」、「無限制創建線程導致 OOM」等痛點,更提供了靈活的參數配置、多樣的隊列策略、完善的生命週期鉤子,讓開發者專注於業務邏輯而非線程管控。本文深度解析線程池核心參數、工作流程、隊列交互規則與調優實戰。
Executor (接口) → execute(Runnable)
↑
ExecutorService (接口) → shutdown、submit、invokeAll、awaitTermination
↑
ThreadPoolExecutor (核心實現類)
↑
ScheduledThreadPoolExecutor (定時任務擴展)
public ThreadPoolExecutor(
int corePoolSize, // 核心線程數
int maximumPoolSize, // 最大線程數
long keepAliveTime, // 非核心線程空閒存活時間
TimeUnit unit, // 時間單位
BlockingQueue workQueue, // 任務隊列
ThreadFactory threadFactory, // 線程工廠 (命名、守護、優先級)
RejectedExecutionHandler handler // 拒絕策略
)
| 參數 | 含義 | 建議設置 | 典型場景 |
|---|---|---|---|
| corePoolSize | 常駐線程數,啟動後不銷毀 (除非 allowCoreThreadTimeOut=true) | CPU 密集: CPU 核心數 + 1 IO 密集: 2 * CPU 核心數 | 固定大小線程池: core=max |
| maximumPoolSize | 允許的最大線程數,超過 core 部分為非核心線程 | 根據任務類型、隊列類型、系統負載綜合評估 | 有界隊列時需較大 max 吸收尖峰 |
| keepAliveTime | 非核心線程空閒超過此時間回收 | 60-300 秒 | 0 表示任務結束即回收 (臨時線程) |
| workQueue | 任務緩衝區,直接影響線程創建/拒絕行為 | 見下節詳細分類 | 核心決策點 |
| threadFactory | 自定義線程名稱、守護屬性、優先級、UncaughtExceptionHandler | 必須設置有意義名稱 (如 "order-process-%d") | 生產環境強制要求,便於排查 |
| handler | 隊列滿且線程達 max 時如何處理新任務 | 見拒絕策略表 | 不可忽視,關係可用性 |
任務提交 execute(task) 時的決策流程:
提交任務
│
├─ 當前線程數 < corePoolSize
│ → 創建新線程執行 (即使有空閒線程)
│
├─ 當前線程數 ≥ corePoolSize
│ ├─ 有空閒線程 → 空閒線程執行
│ └─ 無空閒線程
│ ├─ 隊列未滿 → 入隊等待
│ └─ 隊列已滿
│ ├─ 當前線程數 < maximumPoolSize → 創建新線程執行
│ └─ 當前線程數 ≥ maximumPoolSize → 拒絕策略 handler
│
└─ 任務完成
├─ 線程數 > corePoolSize → 空閒 keepAliveTime 後回收
└─ 線程數 ≤ corePoolSize → 永久阻塞等待新任務 (除非 allowCoreThreadTimeOut)
| 隊列 | 特性 | 行為影響 | 適用場景 | 風險 |
|---|---|---|---|---|
ArrayBlockingQueue | 有界陣列隊列 (FIFO) | 滿則觸發創建線程/拒絕 | 穩定吞吐、需背壓控制 | 隊列長度難調優 |
LinkedBlockingQueue | 無界鏈表隊列 (FIFO) | 永不滿 → maximumPoolSize 失效,永遠只創建 core 線程 | 任務輕量、快速完成、不想拒絕 | 任務堆積導致 OOM |
SynchronousQueue | 零容量直接移交隊列 | 無緩衝 → 必須有線程立即取走,否則創建新線程/拒絕 | 高併發、任務耗時短、追求低延遲 | 尖峰易創建過多線程 |
PriorityBlockingQueue | 優先級隊列 (無界) | 任務按優先級執行,非 FIFO | 有優先級業務 (如 VIP 請求優先) | 優先級反轉、餓死風險 |
core=max=N, ArrayBlockingQueue(cap) — 穩定資源佔用,適合數據庫連接池、HTTP 客戶端池。core=M, max=N, SynchronousQueue — 類似 Executors.newCachedThreadPool() 但可控 max。core=M, max=N, LinkedBlockingQueue — 類似 Executors.newFixedThreadPool() 但可擴展。| 策略 | 行為 | 適用場景 |
|---|---|---|
AbortPolicy (默認) | 拋 RejectedExecutionException | 關鍵業務、需立即感知過載、上層有熔斷/重試 |
CallerRunsPolicy | 調用者線程直接執行任務 | 自然背壓、平滑削峰、不丟任務、不拋異常 |
DiscardPolicy | 靜默丟棄任務 | 非關鍵、可丟失數據 (如監控日志、心跳) |
DiscardOldestPolicy | 丟棄隊列最舊任務,嘗試重新提交 | 優先處理新任務、舊任務可捨 |
| 自定義 | 持久化到磁盤/消息隊列、報警、降級處理 | 高可用要求、需任務不丟失、事後補償 |
public class MonitoredThreadPool extends ThreadPoolExecutor {
private final MetricsCollector metrics;
public MonitoredThreadPool(...) { super(...); this.metrics = ...; }
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
metrics.recordTaskStart(r);
// 可設置 ThreadLocal 計時器、埋點 traceId
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
metrics.recordTaskEnd(r, t);
// 記錄耗時、異常、隊列積壓、線程池狀態
}
@Override
protected void terminated() {
super.terminated();
metrics.reportFinalStats();
}
}
getPoolSize()、getActiveCount()、getCorePoolSize()、getMaximumPoolSize()getQueue().size() / remainingCapacity()getCompletedTaskCount()、getTaskCount()| 工廠方法 | 實際配置 | 風險 | 推薦替代 |
|---|---|---|---|
newFixedThreadPool(n) | core=max=n, LinkedBlockingQueue (無界) | 任務堆積 → OOM | core=max=n, ArrayBlockingQueue(cap) |
newCachedThreadPool() | core=0, max=Integer.MAX_VALUE, SynchronousQueue | 無限創建線程 → CPU 耗盡/OOM | core=M, max=N, SynchronousQueue/LinkedBlockingQueue |
newSingleThreadExecutor() | core=max=1, LinkedBlockingQueue (無界) | 同上 | core=max=1, ArrayBlockingQueue(cap) |
newScheduledThreadPool(n) | core=n, max=Integer.MAX_VALUE, DelayedWorkQueue | 非核心無限創建 | core=n, max=M, 自定義 |
阿里巴巴開發手冊強制要求:不允許使用 Executors 創建線程池,必須手工 new ThreadPoolExecutor 明確參數。
setCorePoolSize()、setMaximumPoolSize() 運行期調整 (配合配置中心)。shutdown() → awaitTermination(timeout) → shutdownNow() 強制中斷。try-catch 吞噬異常或使用 Thread.setDefaultUncaughtExceptionHandler,防止線程意外死亡導致池縮容。ThreadPoolExecutor 以 7 個參數構建出極其豐富的行為空間,掌握「隊列決定線程創建、拒絕策略決定過載行為、鉤子實現可觀測性」三大核心邏輯,即可駕馭從高併發 Web 服務到大數據批次處理的各種場景。拒絕 Executors 懶人寫法,擁抱顯式配置,是併發編程成熟的標誌。