首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 線程池核心原理與 ThreadPoolExecutor 源碼深度解析

     編輯:Java 程式設計入門

線程池核心優勢

  • 降低頻繁創建/銷毀線程的系統開銷。
  • 控制並發數量,防止資源耗盡 (OOM)。
  • 提供定時、延遲、周期性任務支持。
  • 統一管理、監控、異常處理。

Executors 工廠方法與適用場景

方法底層實現特點適用場景
newFixedThreadPool(n)ThreadPoolExecutor(n, n, 0, ms, LinkedBlockingQueue)固定線程數,無界隊列長期任務、需限制並發、服務器端
newSingleThreadExecutor()ThreadPoolExecutor(1, 1, 0, ms, LinkedBlockingQueue)單線程串行,保證順序順序執行任務、單例化資源操作
newCachedThreadPool()ThreadPoolExecutor(0, MAX, 60s, SynchronousQueue)彈性線程數,無隊列直接移交短期異步任務、輕負載、數量不可預估
newScheduledThreadPool(n)ScheduledThreadPoolExecutor支持定時/周期定時任務、心跳檢測、緩存刷新
⚠ 警告:Fixed/Single 使用無界隊列,任務堆積會導致 OOM;Cached 允許無限創建線程,突發流量會撐爆 CPU/內存。**生產環境強烈建議自定義有界隊列與拒絕策略。**

ThreadPoolExecutor 七大參數詳解


public ThreadPoolExecutor(
    int corePoolSize,      // 核心線程數:常駐線程,即使空閒也不回收 (除非 allowCoreThreadTimeOut)
    int maximumPoolSize,   // 最大線程數:隊列滿時可創建的上限
    long keepAliveTime,    // 非核心線程空閒存活時間
    TimeUnit unit,         // 時間單位
    BlockingQueue workQueue, // 任務隊列:有界/無界、FIFO/優先級/同步移交
    ThreadFactory threadFactory,       // 線程工廠:命名、守護線程、優先級、上下文傳遞
    RejectedExecutionHandler handler   // 拒絕策略:隊列滿+線程滿時如何處理
)

常用隊列選型

  • ArrayBlockingQueue:有界數組,FIFO,公平鎖,吞吐一般。
  • LinkedBlockingQueue:無界鏈表 (若不指定容量),FIFO,吞吐高,**固定線程池默認使用,風險大**。
  • SynchronousQueue:零容量,生產者直接移交給消費者,**緩存線程池默認使用**。
  • PriorityBlockingQueue:優先級隊列,無界。

四大內置拒絕策略

  1. AbortPolicy (默認):拋 RejectedExecutionException。
  2. CallerRunsPolicy:調用者線程執行任務,提供「背壓」自然降速。
  3. DiscardOldestPolicy:丟棄隊列頭部最舊任務,嘗試重新提交。
  4. DiscardPolicy:靜默丟棄,不拋異常,不執行。

自定義策略:實現 RejectedExecutionHandler,可記錄日誌、持久化到 DB、發送告警、嘗試緩衝重試。

execute() 執行流程三步曲 (源碼邏輯)


public void execute(Runnable command) {
    // 1. 核心線程未滿 → 直接創建線程執行 (core=true)
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true)) return;
        c = ctl.get();
    }
    // 2. 核心線程滿 → 入隊 (非阻塞 offer)
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // 雙重檢查:線程池被關閉 → 移除任務並拒絕
        if (!isRunning(recheck) && remove(command)) reject(command);
        // 隊列有任務但無線程 (core=0 或意外終止) → 創建非核心線程兜底
        else if (workerCountOf(recheck) == 0) addWorker(null, false);
    }
    // 3. 隊列滿 → 嘗試創建非核心線程 (core=false)
    else if (!addWorker(command, false)) 
        reject(command); // 連非核心也創建失敗 → 拒絕
}

Worker 內部類:線程與任務的綁定

  • 實現 Runnable,持有 firstTask (首個任務) 與 Thread 實例。
  • runWorker() 循環:執行 firstTask → 反覆 getTask() 從隊列取任務執行 → 直到隊列空且線程池縮容或關閉。
  • 鎖控制:mainLock 保護線程集合增減,runWorker 內部無鎖執行任務,並發度高。

生產環境最佳實踐配置範本


@Configuration
public class ThreadPoolConfig {
    @Bean("bizExecutor")
    public ThreadPoolExecutor bizExecutor() {
        return new ThreadPoolExecutor(
            50,                    // core: 業務高峰預期並發
            100,                   // max: 突發緩衝
            60, TimeUnit.SECONDS,  // keepAlive
            new ArrayBlockingQueue<>(2000), // 有界隊列,防 OOM
            new ThreadFactoryBuilder()
                .setNameFormat("biz-worker-%d")
                .setDaemon(false)
                .build(),
            new ThreadPoolExecutor.CallerRunsPolicy() // 背壓,保護下游
        );
    }
}

監控關鍵指標

  • poolSize / activeCount / queue.size() / completedTaskCount / rejectedCount (需自定義計數器)。
  • 整合 Micrometer/Prometheus + Grafana 看板,設置隊列積壓、拒絕率、活躍線程數告警。

總結

線程池不是「配好即忘」,需根據任務類型 (CPU密集/IO密集)、並發模式、下游承受力、SLA 精細調整七大參數。**有界隊列 + CallerRunsPolicy + 完善監控** 是生產環境的鐵三角。理解 execute() 三步曲與 Worker 生命週期,是排查線程池疑難雜癥 (任務卡住、線程不釋放、拒絕風暴) 的前提。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved