線程池是 Java 並發編程的核心基礎設施,能有效控制並發線程數量、減少線程創建銷毀開銷、提升系統吞吐量。本文系統講解 JDK 內置線程池工廠、Fork/Join 框架及生產環境配置建議。
ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
// 提交任務
cacheThreadPool.execute(new Task());
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
newFixedThreadPool(1)。schedule、scheduleAtFixedRate、scheduleWithFixedDelay。ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
// 3 秒後執行一次
scheduledExecutorService.schedule(new Task(), 3, TimeUnit.SECONDS);
// 3 秒後開始,每 5 秒執行一次
scheduledExecutorService.scheduleAtFixedRate(new Task(), 3, 5, TimeUnit.SECONDS);
JDK 7 引入,專為「分治法」設計,適用於可遞歸分解的計算密集型任務。
ForkJoinPool:實現 ExecutorService,管理工作線程。ForkJoinTask:抽象任務類,兩大子類:
RecursiveAction:無返回值任務。RecursiveTask<V>:有返回值任務。static class PrintTask extends RecursiveAction {
private static final int THRESHOLD = 50;
private int start, end;
public PrintTask(int start, int end) { this.start = start; this.end = end; }
@Override protected void compute() {
if (end - start < THRESHOLD) {
for (int i = start; i < end; i++) System.out.println(Thread.currentThread().getName() + " " + i);
} else {
int middle = (start + end) / 2;
PrintTask left = new PrintTask(start, middle);
PrintTask right = new PrintTask(middle, end);
left.fork(); right.fork(); // 提交子任務並行執行
}
}
}
static class CalTask extends RecursiveTask<Integer> {
private static final int THRESHOLD = 20;
private int[] arr; private int start, end;
public CalTask(int[] arr, int start, int end) { this.arr = arr; this.start = start; this.end = end; }
@Override protected Integer compute() {
if (end - start < THRESHOLD) {
int sum = 0;
for (int i = start; i < end; i++) sum += arr[i];
return sum;
} else {
int middle = (start + end) / 2;
CalTask left = new CalTask(arr, start, middle);
CalTask right = new CalTask(arr, middle, end);
left.fork(); right.fork();
return left.join() + right.join(); // 合併結果
}
}
}
| 場景 | 推薦線程池 | 核心參數調優 |
|---|---|---|
| CPU 密集型計算 | FixedThreadPool / ForkJoinPool | 核心線程數 = CPU 核心數 + 1 |
| IO 密集型任務 | FixedThreadPool / CachedThreadPool | 核心線程數 = CPU 核心數 * (1 + 平均等待時間/平均工作時間) |
| 定時任務 | ScheduledThreadPool | corePoolSize 根據並發定時任務數設定 |
| 高並發短任務 | 自定義 ThreadPoolExecutor | 有界隊列 + 拒絕策略 + 監控指標 |
ThreadFactoryBuilder.setNameFormat("order-process-%d") 便於排查。LinkedBlockingQueue 無界導致 OOM,改用 ArrayBlockingQueue。CallerRunsPolicy 由調用者執行,緩衝突發壓力。shutdown() 後配合 awaitTermination 等待任務完成。合理選擇與配置線程池是 Java 高併發系統穩定運行的基石。Executors 提供的四種預設池適用於簡單場景,複雜業務建議直接使用 ThreadPoolExecutor 自定義參數;計算密集型分治任務優先考慮 ForkJoinPool。持續監控與壓測驗證是保障線程池健康的關鍵。