【JDK源碼分析系列】ThreadPoolExecutor 源碼解析 -- 基本屬性分析

【JDK源碼分析系列】ThreadPoolExecutor 源碼解析 -- 基本屬性分析

【1】ThreadPoolExecutor 的基本屬性 -- 常量與變量

//ctl 線程池狀態控制字段,由兩部分組成:
//1:workerCount  有效的線程數,workerCount 最大是到(2^29)-1,大概 5 億個線程
//2:runState 線程池的狀態,提供了生命週期的控制,源碼中有很多關於狀態的校驗,狀態枚舉如下:
//RUNNING(-536870912):接受新任務或者處理隊列裏的任務;
//SHUTDOWN(0):不接受新任務,但仍在處理已經在隊列裏面的任務;
//STOP(536870912):不接受新任務,也不處理隊列中的任務,對正在執行的任務進行中斷;
//TIDYING(1073741824): 所以任務都被中斷,workerCount 是 0,整理狀態;
//TERMINATED(1610612736): terminated() 已經完成的時候;

//runState 之間的轉變過程:
//RUNNING -> SHUTDOWN:調用 shudown(),finalize()
//(RUNNING or SHUTDOWN) -> STOP:調用shutdownNow()
//SHUTDOWN -> TIDYING -> workerCount ==0
//STOP -> TIDYING -> workerCount ==0
//TIDYING -> TERMINATED -> terminated() 執行完成之後
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;// 29
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;// =(2^29)-1=536870911

// Packing and unpacking ctl
// 對 ctl 字段進行拆包與封裝處理,獲取其中的 workercount 和 runstate
private static int ctlOf(int rs, int wc) { return rs | wc; }
private static int workerCountOf(int c)  { return c & CAPACITY; }
private static int runStateOf(int c)     { return c & ~CAPACITY; }

// runState is stored in the high-order bits
// runstate 的各種狀態的定義值
private static final int RUNNING    = -1 << COUNT_BITS;//-536870912
private static final int SHUTDOWN   =  0 << COUNT_BITS;//0
private static final int STOP       =  1 << COUNT_BITS;//536870912
private static final int TIDYING    =  2 << COUNT_BITS;//1073741824
private static final int TERMINATED =  3 << COUNT_BITS;//1610612736

// 已完成任務的計數
volatile long completedTasks;
// 線程池最大容量
private int largestPoolSize;
// 已經完成的任務數
private long completedTaskCount;
// 用戶可控制的參數都是 volatile 修飾的
// 創建失敗一般不拋出異常,只有在 OutOfMemoryError 時候纔會
// 可以使用 threadFactory 創建 thread
private volatile ThreadFactory threadFactory;
// 飽和或者運行中拒絕任務的 handler 處理類
private volatile RejectedExecutionHandler handler;
// 線程存活時間設置
private volatile long keepAliveTime;
// 設置 true 的話,核心線程空閒 keepAliveTime 時間後,也會被回收
private volatile boolean allowCoreThreadTimeOut;
// coreSize
// 核心線程數量
private volatile int corePoolSize;
// maxSize 最大限制 (2^29)-1
private volatile int maximumPoolSize;
// 默認的拒絕策略
private static final RejectedExecutionHandler defaultHandler =
    new AbortPolicy();

// 隊列會 hold 住任務,並且利用隊列的阻塞的特性,來保持線程的存活週期
private final BlockingQueue<Runnable> workQueue;

// 大多數情況下是控制對 workers 的訪問權限
// 可重入鎖以及對應的條件變量
private final ReentrantLock mainLock = new ReentrantLock();
private final Condition termination = mainLock.newCondition();

// 包含線程池中所有的工作線程
private final HashSet<Worker> workers = new HashSet<Worker>();

【2】ThreadPoolExecutor 的基本屬性 -- Worker 類

// 線程池中任務運行的最小單元
// 維護着運行中的任務的線程鎖和可中斷狀態
// Worker 繼承 AQS,具有鎖功能
// Worker 實現 Runnable,本身是一個可執行的任務
//
// 1. Worker 任務的代理,在線程池中,最小的執行單位就是 Worker,因此 Worker 實現了 Runnable 接口,實現了 run 方法;
// 2. 在 Worker 初始化時 this.thread = getThreadFactory ().newThread (this) 這行代碼
//    把當前 Worker 作爲線程的構造器入參,
//    在後續的實現中會發現這樣的代碼:Thread t = w.thread;t.start (),
//    此時的 w 是 Worker 的引用申明,此處 t.start 實際上執行的就是 Worker 的 run 方法;
// 3. Worker 本身也實現了 AQS,所以其本身也是一個鎖,其在執行任務的時候,會鎖住自己,任務執行完成之後,會釋放自己;
private final class Worker
    extends AbstractQueuedSynchronizer
    implements Runnable
{
    // 任務運行的線程
    final Thread thread;

    // 需要執行的任務
    Runnable firstTask;

    // 非常巧妙的設計,Worker本身是個 Runnable,把自己作爲任務傳遞給 thread
    // 內部有個屬性又設置了 Runnable
    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker
        this.firstTask = firstTask;
        // 把 Worker 自己作爲 thread 運行的任務
        this.thread = getThreadFactory().newThread(this);
    }

    /** Worker 本身是 Runnable,run 方法是 Worker 執行的入口, runWorker 是外部的方法 */
    public void run() {
        runWorker(this);
    }

    private static final long serialVersionUID = 6138294804551838833L;

    // Lock methods
    // 0 代表沒有鎖住,1 代表鎖住
    protected boolean isHeldExclusively() {
        return getState() != 0;
    }
    // 嘗試加鎖,CAS 賦值爲 1,表示鎖住
    // 重寫了 AbstractQueuedSynchronizer 類的 tryAcquire 方法
    protected boolean tryAcquire(int unused) {
        if (compareAndSetState(0, 1)) {
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }
    // 嘗試釋放鎖,釋放鎖沒有 CAS 校驗,可以任意的釋放鎖
    // 重寫了 AbstractQueuedSynchronizer 類的 tryRelease 方法
    protected boolean tryRelease(int unused) {
        setExclusiveOwnerThread(null);
        setState(0);
        return true;
    }
    //加鎖方法
    //調用了 AbstractQueuedSynchronizer 的 acquire 方法
    public void lock()        { acquire(1); }
    //嘗試加鎖方法
    public boolean tryLock()  { return tryAcquire(1); }
    //解鎖方法
    public void unlock()      { release(1); }
    //判斷是否已經獲取鎖
    public boolean isLocked() { return isHeldExclusively(); }
    //若線程已經啓動則將該線程中斷
    void interruptIfStarted() {
        Thread t;
        if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
            try {
                t.interrupt();
            } catch (SecurityException ignore) {
            }
        }
    }
}

參考致謝
本博客爲博主的學習實踐總結,並參考了衆多博主的博文,在此表示感謝,博主若有不足之處,請批評指正。

【1】37 ThreadPoolExecutor 源碼解析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章