Java 執行緒池完整實戰指南:四大類型、定時任務與優雅關閉
Executors 工具類提供標準執行緒池與定時器建立方式。
四大標準執行緒池
| 類型 | 建立方法 | 核心特性 | 適用場景 |
| FixedThreadPool |
newFixedThreadPool(n) |
固定 n 條執行緒、無界 LinkedBlockingQueue、任務可能無限積壓 |
長期運行、任務量可控、需限制並發度 |
| SingleThreadExecutor |
newSingleThreadExecutor() |
單執行緒循序執行、無界隊列、執行緒死掉自動重建 |
需嚴格循序處理的任務(日誌、序列化) |
| CachedThreadPool |
newCachedThreadPool() |
動態伸縮、SynchronousQueue(無容量)、60 秒閒置回收 |
大量短期非同步任務、任務耗時短 |
| ScheduledThreadPool |
newScheduledThreadPool(n) |
DelayQueue、支援定時/週期任務 |
定時備份、心跳檢測、延遲重試 |
程式碼範例
1. FixedThreadPool - 固定 3 條執行緒處理 10 個任務
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int j = 0; j < 10; j++) {
final int taskId = j;
pool.execute(() -> {
for (int i = 0; i < 10; i++) {
try { Thread.sleep(200); } catch (InterruptedException ignored) {}
System.out.println(Thread.currentThread().getName()
+ " loop " + i + " task " + taskId);
}
});
}
2. CachedThreadPool - 動態伸縮
ExecutorService pool = Executors.newCachedThreadPool();
// 相同提交邏輯,執行緒數會隨任務量自動增減
3. SingleThreadExecutor - 單執行緒循序
ExecutorService pool = Executors.newSingleThreadExecutor();
// 任務嚴格按提交順序執行,適合需序列化的場景
關閉策略:shutdown vs shutdownNow
| 方法 | 行為 | 已提交任務 | 執行中任務 | 返回值 |
shutdown() |
優雅關閉 |
繼續執行 |
繼續執行 |
void |
shutdownNow() |
強制關閉 |
返回列表(未執行) |
嘗試 interrupt() 中斷 |
List<Runnable> |
最佳實踐:
pool.shutdown();
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
System.err.println("Pool did not terminate");
}
}
} catch (InterruptedException ex) {
pool.shutdownNow();
Thread.currentThread().interrupt();
}
ScheduledExecutorService - 定時任務三大方法
1. schedule - 單次延遲執行
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3);
scheduler.schedule(() -> {
System.out.println("延遲 2 秒執行: " + Thread.currentThread().getName());
}, 2, TimeUnit.SECONDS);
2. scheduleAtFixedRate - 固定頻率執行
// 初始延遲 2 秒,之後每 3 秒執行一次
// 若任務執行時間 > 週期,後續執行會推遲(不會並發執行同一任務)
scheduler.scheduleAtFixedRate(() -> {
System.out.println("固定頻率: " + Thread.currentThread().getName());
}, 2, 3, TimeUnit.SECONDS);
3. scheduleWithFixedDelay - 固定延遲執行
// 初始延遲 2 秒,每次執行結束後等待 3 秒再執行下一次
// 適合需確保間隔時間的場景
scheduler.scheduleWithFixedDelay(() -> {
System.out.println("固定延遲: " + Thread.currentThread().getName());
}, 2, 3, TimeUnit.SECONDS);
對比總結
| 特性 | scheduleAtFixedRate | scheduleWithFixedDelay |
| 間隔基準 |
上次開始時間 |
上次結束時間 |
| 執行時間 > 間隔 |
推遲後續執行 |
正常等待間隔後執行 |
| 適用場景 |
固定頻率采樣、心跳 |
需冷卻時間的任務、外部 API 限流 |
生產環境建議
- 避免直接使用 Executors:《阿里巴巴 Java 開發手冊》建議自定義
ThreadPoolExecutor,明確核心參數(corePoolSize、maximumPoolSize、keepAliveTime、workQueue、ThreadFactory、RejectedExecutionHandler)
- 有界隊列:防止任務積壓導致 OOM,拒絕策略用
CallerRunsPolicy 讓提交執行緒回滾執行
- 命名執行緒:自定義
ThreadFactory 設定有意義名稱(如 order-process-%d),便於排查
- 監控指標:隊列長度、活躍執行緒數、完成任務數、拒絕任務數
// 生產級自定義執行緒池範例
ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, 8, // core / max
60L, TimeUnit.SECONDS, // keepAlive
new ArrayBlockingQueue<>(1000), // 有界隊列
new ThreadFactoryBuilder().setNameFormat("order-process-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略
);