為什麼需要線程池?
- 線程創建/銷毀涉及 OS 交互,成本高。
- 無限制創建導致 OOM、CPU 抖動、JVM 崩潰。
- 池化復用 + 佇列緩衝 + 拒絕策略 = 穩定可控並發。
Executors 工廠五大標準池
| 工廠方法 | 特性 | 適用場景 | 底層實現 |
newCachedThreadPool() | 無界,閒置 60s 回收,新任務新建線程 | 短耗時、突發性任務 | ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>()) |
newFixedThreadPool(n) | 固定 n 線程,無界佇列 | 長耗時、需限制並發度 | ThreadPoolExecutor(n, n, 0L, ms, new LinkedBlockingQueue<>()) |
newSingleThreadExecutor() | 單線程串行,保證任務順序 | 順序執行、單一資源訪問 | new FinalizableDelegatedExecutorService(new FixedThreadPool(1)) |
newScheduledThreadPool(n) | 定時/周期執行,支援 scheduleAtFixedRate | 定時任務、心跳檢測 | ScheduledThreadPoolExecutor |
newSingleThreadScheduledExecutor() | 單線程定時 | 單一定時任務 | ScheduledThreadPoolExecutor(1) |
代碼實戰演示
CachedThreadPool 線程復用
ExecutorService pool = Executors.newCachedThreadPool();
for (int i=0;i<3;i++) pool.execute(new Task()); // 創建 3 線程
Thread.sleep(3000);
for (int i=0;i<3;i++) pool.execute(new Task()); // 復用前 3 線程
// 輸出:pool-1-thread-1/2/3 反覆出現
FixedThreadPool 固定並發
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i=0;i<8;i++) pool.execute(new Task());
// 8 個任務由 3 線程輪流執行,佇列緩衝
ScheduledThreadPool 定時周期
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
pool.schedule(task, 3, TimeUnit.SECONDS); // 延遲 3s 執行一次
pool.scheduleAtFixedRate(task, 3, 5, TimeUnit.SECONDS); // 3s 後每 5s 執行
Thread.sleep(30000); pool.shutdown();
ForkJoinPool:分治並行計算
- 專為「大任務拆分 → 並行子任務 → 合併結果」設計(MapReduce 模式)。
- 工作盜演算法:閒置線程竊取忙碌線程雙端佇列尾部任務,負載均衡。
RecursiveAction(無返回值)
static class PrintTask extends RecursiveAction {
static final int THRESHOLD = 50;
int start, end;
@Override protected void compute() {
if (end - start < THRESHOLD) {
for (int i=start;i
RecursiveTask<T>(有返回值)
static class SumTask extends RecursiveTask<Integer> {
static final int THRESHOLD = 20;
int[] arr; int start, end;
@Override protected Integer compute() {
if (end - start < THRESHOLD) {
int sum=0; for(int i=start;i
生產級調優清單
- 拒絕 Executors 默認工廠:阿里規約強制自定義
ThreadPoolExecutor,明確佇列類型(有界 ArrayBlockingQueue)與拒絕策略(CallerRunsPolicy 回壓)。
- 核心參數計算:
- CPU 密集:核心數 = CPU 核心數 + 1
- IO 密集:核心數 = CPU 核心數 * (1 + 平均等待時間/平均工作時間)
- 監控指標:
activeCount、queue.size()、completedTaskCount、rejectCount。
- 線程命名:
new ThreadFactoryBuilder().setNameFormat("order-process-%d").build() 便於排查。
- 優雅關閉:
shutdown() + awaitTermination(timeout),避免任務丟失。