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

Java 執行緒池核心原理解析:ThreadPoolExecutor 源碼深度剖析與最佳實踐

     編輯:Java 相關知識

執行緒池核心優勢

避免頻繁建立/銷毀執行緒開銷,透過 Executor 介面解耦任務提交與執行,ThreadPoolExecutor 是核心實作(基於 JDK 1.7 源碼分析)。

生命週期狀態機

使用 AtomicInteger ctl 高 3 位表示狀態,低 29 位表示執行緒數:

狀態說明轉換條件
RUNNING接受新任務,處理隊列任務初始狀態
SHUTDOWN拒絕新任務,處理隊列任務呼叫 shutdown()
STOP拒絕新任務,拋棄隊列,中斷執行中任務呼叫 shutdownNow()
TIDYING所有任務終止,執行緒數為 0任務隊列空且無作用中執行緒
TERMINATEDterminated() 執行完成TIDYING 狀態結束

四大核心參數與四種預設模型

參數說明
corePoolSize核心執行緒數(常駐,除非 allowCoreThreadTimeOut)
maximumPoolSize最大執行緒數(受限於 CAPACITY = 2^29-1)
keepAliveTime非核心執行緒閒置存活時間
workQueue任務隊列(BlockingQueue 實作)
RejectedExecutionHandler拒絕策略(隊列滿且達最大執行緒時觸發)

Executors 四種預設模型

模型core/max隊列特性適用場景
FixedThreadPooln/nLinkedBlockingQueue (無界)固定大小,任務排隊長期穩定負載
CachedThreadPool0/Integer.MAX_VALUESynchronousQueue (直接交接)彈性伸縮,閒置回收短期大量突發任務
SingleThreadExecutor1/1LinkedBlockingQueue串行執行,保證順序序列化任務處理
ScheduledThreadPoolcore/Integer.MAX_VALUEDelayedWorkQueue定時/週期性任務替代 Timer

execute() 核心執行流程

public void execute(Runnable command) {
    int c = ctl.get();
    // 1. 執行緒數 < corePoolSize → 新建核心執行緒
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true)) return;
        c = ctl.get();
    }
    // 2. 執行緒數 >= corePoolSize → 入隊列
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // 雙重檢查:狀態變更或執行緒為 0
        if (!isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false); // 確保至少一個執行緒
    }
    // 3. 隊列滿 → 嘗試新建非核心執行緒
    else if (!addWorker(command, false))
        // 4. 失敗 → 拒絕策略
        reject(command);
}

四階段運作模式

  1. Phase 1:poolSize < corePoolSize,隊列空 → 直接新建核心執行緒
  2. Phase 2:poolSize == corePoolSize → 任務入隊列,核心執行緒消費
  3. Phase 3:隊列滿,poolSize < maxPoolSize → 新建非核心執行緒
  4. Phase 4:poolSize == maxPoolSize 且隊列滿 → 觸發拒絕策略

Worker 內部類與 runWorker() 核心邏輯

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // 釋放 AQS 鎖
    
    while (task != null || (task = getTask()) != null) {
        w.lock(); // 獲取 AQS 獨佔鎖
        try {
            beforeExecute(wt, task); // 擴展點:子類覆寫
            task.run();
            afterExecute(task, null); // 擴展點
        } catch (Throwable ex) {
            afterExecute(task, ex);
            throw ex;
        } finally {
            task = null;
            w.unlock();
        }
    }
    processWorkerExit(w, false); // 清理
}

getTask() 任務獲取與執行緒回收

private Runnable getTask() {
    boolean timed = allowCoreThreadTimeOut || workerCount > corePoolSize;
    Runnable r = timed ? 
        workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : // 超時輪詢
        workQueue.take(); // 阻塞等待
    
    if (r == null) {
        // 四種回收條件:
        // 1. 執行緒數 > maximumPoolSize
        // 2. 狀態 == STOP
        // 3. 狀態 == SHUTDOWN 且隊列空
        // 4. 超時且執行緒數 > corePoolSize
        return null; // 觸發 processWorkerExit
    }
    return r;
}

四種拒絕策略對比

策略行為適用場景
AbortPolicy (預設)拋出 RejectedExecutionException關鍵任務不可丟失,需即時感知
CallerRunsPolicy呼叫者執行緒同步執行任務緩衝壓力,不拋異常,不丟任務(推薦)
DiscardPolicy靜默丟棄任務非關鍵、可容忍丟失的任務
DiscardOldestPolicy丟棄隊列最舊任務,執行新任務優先處理新請求的場景

自定義執行緒池最佳實踐

public class CustomThreadPool {
    public static ThreadPoolExecutor create() {
        return new ThreadPoolExecutor(
            4,                    // corePoolSize: CPU 核心數 * (1 + 平均等待/計算比)
            8,                    // maximumPoolSize
            60L, TimeUnit.SECONDS, // keepAliveTime
            new LinkedBlockingQueue<>(100), // 有界隊列,防止 OOM
            new ThreadFactoryBuilder()
                .setNameFormat("biz-worker-%d")
                .setDaemon(false)
                .build(),
            new ThreadPoolExecutor.CallerRunsPolicy() // 推薦策略
        );
    }
    
    // 擴展監控:覆寫 before/afterExecute
    static class MonitoredPool extends ThreadPoolExecutor {
        @Override protected void beforeExecute(Thread t, Runnable r) {
            super.beforeExecute(t, r);
            // 記錄任務開始時間、執行緒資訊
        }
        @Override protected void afterExecute(Runnable r, Throwable t) {
            super.afterExecute(r, t);
            // 記錄耗時、異常、隊列積壓
        }
    }
}

隊列選型指南

隊列類型特性搭配建議
ArrayBlockingQueue有界陣列、FIFO固定大小、公平鎖、預測負載
LinkedBlockingQueue無界鏈表、FIFOFixedThreadPool、可能 OOM 風險
SynchronousQueue零容量、直接交接CachedThreadPool、即時執行
PriorityBlockingQueue優先級排序任務有優先級區分
DelayedWorkQueue延遲執行排序ScheduledThreadPool 專用

監控關鍵指標

  • getActiveCount():正在執行任務的執行緒數
  • getQueue().size():待執行任務數(積壓指標)
  • getCompletedTaskCount():已完成任務總數
  • getTaskCount():總提交任務數
  • 拒絕次數:自行計數或 JMX 監控
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved