頻繁創建/銷毀線程開銷巨大,線程池技術復用線程、控制併發數、管理任務隊列,是高併發系統必備組件。本文深度解析 JDK Executor 框架核心接口、四大預定義線程池、自定義配置七大參數,並通過實戰案例演示最佳實踐。
| 痛點 | 線程池解決方案 |
|---|---|
| 頻繁創建/銷毀線程消耗 CPU/內存 | 線程復用,任務結束不銷毀線程,繼續從隊列取任務 |
| 無限制創建線程導致 OOM | 核心/最大線程數限制,隊列緩衝,拒絕策略兜底 |
| 任務調度/管理困難 | 統一提交入口,支持定時/周期/延遲任務 |
| 缺乏監控指標 | 提供隊列長度、活躍線程數、完成任務數等監控數據 |
Executor (頂級接口,僅 execute(Runnable))
↓ 繼承
ExecutorService (生命周期管理、提交任務返回 Future、批量提交)
↓ 實現
ThreadPoolExecutor (核心實現,七大參數完全可控)
↓ 工廠方法
Executors (工廠類,提供四大預定義池)
| 方法 | 核心線程數 | 最大線程數 | 隊列類型 | 適用場景 | 風險 |
|---|---|---|---|---|---|
| newFixedThreadPool(n) | n | n | LinkedBlockingQueue (無界) | 長期任務、固定併發 | 隊列無界,任務積壓致 OOM |
| newCachedThreadPool() | 0 | Integer.MAX_VALUE | SynchronousQueue (直遞) | 短期異步任務、輕量級 | 線程數無上限,突發流量致 OOM |
| newSingleThreadExecutor() | 1 | 1 | LinkedBlockingQueue (無界) | 串行執行、順序任務 | 隊列無界,單點阻塞 |
| newScheduledThreadPool(n) | n | Integer.MAX_VALUE | DelayedWorkQueue (延遲隊列) | 定時/周期任務 | 非核心線程無上限 |
阿里巴巴開發手冊強制規定:不允許使用 Executors 創建線程池,必須通過 ThreadPoolExecutor 自定義,明確業務邊界。
public ThreadPoolExecutor(
int corePoolSize, // 核心線程數(常駐)
int maximumPoolSize, // 最大線程數(峰值)
long keepAliveTime, // 非核心線程存活時間
TimeUnit unit, // 時間單位
BlockingQueue workQueue, // 任務隊列
ThreadFactory threadFactory, // 線程工廠(命名、守護線程設置)
RejectedExecutionHandler handler // 拒絕策略
)
ArrayBlockingQueue 或 LinkedBlockingQueue(capacity) 防止 OOMPriorityBlockingQueue 實現任務優先級AbortPolicy(默認):拋出異常,關鍵業務CallerRunsPolicy:調用者線程執行,平滑限流DiscardOldestPolicy:丟棄最老任務,非核心業務DiscardPolicy:靜默丟棄,日誌類業務new ThreadFactoryBuilder().setNameFormat("order-process-%d").build()(Guava)便於排查問題@Configuration
public class ThreadPoolConfig {
@Bean("orderThreadPool")
public ThreadPoolExecutor orderThreadPool() {
return new ThreadPoolExecutor(
8, // 核心線程數
16, // 最大線程數
60L, TimeUnit.SECONDS,// 非核心線程存活 60s
new LinkedBlockingQueue<>(2000), // 有界隊列 2000
new ThreadFactoryBuilder()
.setNameFormat("order-async-%d")
.setDaemon(false)
.build(),
new ThreadPoolExecutor.CallerRunsPolicy() // 平滑限流
);
}
}
// 業務使用
@Service
public class OrderService {
@Autowired @Qualifier("orderThreadPool")
private ThreadPoolExecutor orderThreadPool;
public void asyncProcess(Order order) {
orderThreadPool.execute(() -> {
try {
// 耗時操作:發送 MQ、調用三方、寫入 ES 等
processOrderDetail(order);
} catch (Exception e) {
log.error("訂單異步處理失敗", e);
// 補償機制:寫入死信隊列、告警等
}
});
}
}
getActiveCount():當前活躍線程數getQueue().size():隊列堆積任務數getCompletedTaskCount():歷史完成任務數getTaskCount():總提交任務數// 1. 停止接收新任務
threadPool.shutdown(); // 不再接受新任務,已提交任務繼續執行
// 2. 等待任務完成(設定超時)
try {
if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
// 3. 強制關閉未完成任務
List remaining = threadPool.shutdownNow();
log.warn("線程池強制關閉,剩余 {} 個任務未執行", remaining.size());
// 持久化剩余任務到 DB/MQ 供後續重試
}
} catch (InterruptedException e) {
threadPool.shutdownNow();
Thread.currentThread().interrupt();
}
Executors 預定義池,務必自定義 ThreadPoolExecutor