在高併發場景下,頻繁創建銷毀線程會帶來巨大的系統開銷:線程創建需要分配棧內存、向 OS 申請資源;銷毀涉及上下文切換與資源回收。線程池通過線程複用與任務隊列緩衝,實現了「以空間換時間」的效能優化,同時避免了無限制創建線程導致的 OOM 風險。
| 線程池類型 | 核心特性 | 適用場景 | 風險提示 |
|---|---|---|---|
newFixedThreadPool | 固定核心線程數,無界隊列(LinkedBlockingQueue),線程不回收 | 長期運行、任務量穩定的業務 | 任務堆積時記憶體飆升,拒絕策略默認 AbortPolicy |
newCachedThreadPool | 核心線程 0,最大 Integer.MAX_VALUE,60s 空閒回收,同步移交隊列 | 短時高併發、任務執行快的場景 | 任務提交速度>執行速度時會無限創建線程,導致 CPU 竄頻甚至 OOM |
newSingleThreadExecutor | 單線程串行執行,保證任務順序性,線程異常自動重啟 | 順序處理、不需併發的串行任務 | 單點瓶頸,任務堆積無法並行處理 |
newScheduledThreadPool | 支援定時/週期性任務,基於 DelayedWorkQueue | 定時任務、延遲執行、週期性作業 | 長周期任務阻塞會影響後續調度精度 |
public ThreadPoolExecutor(
int corePoolSize, // 核心線程數(常駐)
int maximumPoolSize, // 最大線程數(峰值)
long keepAliveTime, // 非核心線程存活時間
TimeUnit unit, // 時間單位
BlockingQueue<Runnable> workQueue, // 任務隊列
ThreadFactory threadFactory, // 線程工廠
RejectedExecutionHandler handler // 拒絕策略
)
AbortPolicy(默認):拋出 RejectedExecutionExceptionCallerRunsPolicy:調用者線程執行任務,實現「削峰填谷」背壓效果DiscardPolicy:靜默丟棄新任務DiscardOldestPolicy:丟棄隊列最老任務,嘗試重新提交public class ThreadPoolMonitorDemo {
private static final int CORE_SIZE = 5;
private static final int MAX_SIZE = 10;
private static final int QUEUE_CAPACITY = 100;
public static void main(String[] args) {
// 1. 自定義線程工廠:命名+守護線程設置
ThreadFactory namedFactory = new ThreadFactoryBuilder()
.setNameFormat("biz-processor-%d")
.setDaemon(false)
.build();
// 2. 創建可監控的線程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
CORE_SIZE, MAX_SIZE, 60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(QUEUE_CAPACITY),
namedFactory,
new ThreadPoolExecutor.CallerRunsPolicy() // 背壓策略
);
// 3. 異步監控線程池狀態
ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
monitor.scheduleAtFixedRate(() -> {
System.out.printf("[Pool Monitor] Active: %d, Pool: %d, Queue: %d, Completed: %d%n",
executor.getActiveCount(),
executor.getPoolSize(),
executor.getQueue().size(),
executor.getCompletedTaskCount()
);
}, 0, 5, TimeUnit.SECONDS);
// 4. 提交測試任務
IntStream.rangeClosed(1, 200).forEach(i ->
executor.execute(() -> {
try { Thread.sleep(200); } catch (InterruptedException ignored) {}
})
);
// 5. 優雅關閉
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
executor.shutdown();
monitor.shutdown();
try {
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}));
}
}
線程池並非「配置好即忘記」的基礎設施。理解其參數交互模型、隊列與拒絕策略的協作機制、監控指標的業務含義,才能在高併發系統中發揮最大效能。建議採用自定義 ThreadPoolExecutor替代 Executors 工廠方法,實現參數顯式化、命名可追蹤、策略可控制的工程化管理。