ExecutorService es = Executors.newCachedThreadPool();
for (int i = 1; i < 8000; i++) {
es.submit(new Task()); // Task 執行 4 秒
}
執行結果:
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.util.concurrent.ThreadPoolExecutor.addIfUnderMaximumPoolSize(...)
at java.util.concurrent.ThreadPoolExecutor.execute(...)
at java.util.concurrent.AbstractExecutorService.submit(...)
"Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available... If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache."
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(
0, Integer.MAX_VALUE, // core=0, max=Integer.MAX_VALUE
60L, TimeUnit.SECONDS, // 60秒閒置回收
new SynchronousQueue<Runnable>() // 零容量同步佇列
);
}
SynchronousQueue 無緩衝,每個任務必須直接移交給執行緒Integer.MAX_VALUE 無上限)OutOfMemoryError: unable to create new native threadclass LogThreadPoolExecutor extends ThreadPoolExecutor {
protected void beforeExecute(Thread t, Runnable r) {
System.out.println(t.getName()); // 印出執行緒名稱
}
protected void afterExecute(Runnable r, Throwable t) {}
}
// 測試
ExecutorService es = new LogThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
for (int i = 0; i < 8000; i++) es.submit(new LongTask());
實測結果:Windows 平台約建立 5592 條執行緒即崩潰(受限於系統預設執行緒數上限)。
ExecutorService es = new ThreadPoolExecutor(
10, // corePoolSize
100, // maximumPoolSize:根據業務壓測設定
60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(200), // 有界佇列,防止任務無限堆積
new ThreadFactoryBuilder().setNameFormat("biz-worker-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy() // 背壓:提交執行緒直接執行
);
優點:完全可控、支援背壓、生產環境最佳實踐。
Semaphore 限制併發提交數Guava RateLimiter 平滑限流-Xss256k 減少執行緒棧大小(謹慎使用,可能導致 StackOverflow)ulimit -u、/proc/sys/kernel/pid_max設計初衷:針對「大量短生命週期任務」優化吞吐量。若任務極短(毫秒級),執行緒快速建立/銷毀/複用,峰值併發雖高但持續時間極短,通常不會觸及系統極限。但開發者常誤用於長耗時任務,導致執行緒長期佔用、快速累積。
| 場景 | 推薦線程池 | 關鍵配置 |
|---|---|---|
| CPU 密集型、固定併發 | FixedThreadPool / 自訂 | 核心數 = CPU核心數+1,有界佇列 |
| IO 密集型、併發波動大 | 自訂 ThreadPoolExecutor | 核心數參考公式,最大數設上限,有界佇列 + CallerRunsPolicy |
| 大量極短任務(毫秒級) | CachedThreadPool 可接受 | 監控峰值執行緒數,必要時遷移至自訂 |
| 定時/週期性任務 | ScheduledThreadPoolExecutor | 單一執行緒調度器 + 任務執行線程池分離 |
CachedThreadPool 並非「銀彈」,其 maximumPoolSize = Integer.MAX_VALUE 設計假設任務極短。生產環境**強烈建議避免直接使用 Executors 預設工廠方法**,改用自訂 ThreadPoolExecutor 明確聲明:核心數、最大數、佇列類型與容量、拒絕策略、執行緒命名。唯有參數顯性化,才能構建可觀測、可控制、可演進的併發系統。