線程池execute源碼

/**
     * Executes the given task sometime in the future.  The task
     * may execute in a new thread or in an existing pooled thread.
     * 在未來某個時間執行指定傳入的任務。
     * 任務可以在一個新線程中執行,也可能在線程池中已存在的一個線程中執行。
     * If the task cannot be submitted for execution, either because this
     * executor has been shutdown or because its capacity has been reached,
     * the task is handled by the current {@code RejectedExecutionHandler}.
     * 如果這個任務不能被提交執行,或者是因爲這個executor已經被shutdown,又或者因爲已經觸及線程池的最大容量,
     * 這個任務被當前的拒絕策略RejectedExecutionHandler處理掉了
     * @param command the task to execute
     * @throws RejectedExecutionException at discretion of
     *         {@code RejectedExecutionHandler}, if the task
     *         cannot be accepted for execution
     * @throws NullPointerException if {@code command} is null
     */
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
         /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         * 如果線程池當前正在運行的線程數小於corePoolSize,將嘗試新起一個線程,傳入的Runnable command將作爲它的第一個任務。
         * 調用addWorker將原子性的檢查runState線程池運行狀態和workerCount工作者數量,並且當不應該新增線程時通過return false來阻止。
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         * 如果一個任務能夠成功的加入隊列,這時我們仍然需要再次檢查我們是否應該新起一個線程(因爲從上次檢查之後已存在的線程有可能消亡了)
         * 或者進入此方法後線程池shutdown了。
         * 所以我們還是要重新檢查線程池狀態,以及當線程池停止是否有必要將入隊列的操作回滾,
         * 或者線程池中沒有線程時需要新起一個線程
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         * 如果不能將任務入隊列,這時我們嘗試新起一個線程,如果新起線程失敗,我們就知道線程池已經被shutdown或者線程池飽和了,
         * 這時就需要拒絕任務了
         */
       int c = ctl.get();
        //如果worker的數量小於corePoolSize
        if (workerCountOf(c) < corePoolSize) {
            //如果添加任務成功就可以返回了
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        //如果workerCount不小於核心線程數,那麼接下來嘗試放到blockingqueue了
        //ctl<SHUTDOWN且入隊列成功
        if (isRunning(c) && workQueue.offer(command)) {
            //二次檢查ctl
            int recheck = ctl.get();
            //ctl>=SHUTDOWN且移除任務成功
            if (! isRunning(recheck) && remove(command))
                //拒絕任務
                reject(command);
                //如果workerCount==0,這時候創建空的worker,使用maximumPoolSize
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //接下來是嘗試添加超過corePoolSize,<=maximumPoolSize,如果添加失敗則採用拒絕策略
        else if (!addWorker(command, false))
            reject(command);
    }
 private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            //得到ctl
            int c = ctl.get();
            //c & ~CAPACITY 只保留高3位狀態位1
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            //3種情況,1、線程池>SHUTDOWN
            // 2、線程池狀態==SHUTDOWN 且firstTask != null
            // 3、線程池狀態==SHUTDOWN 且firstTask == null且workQueue.isEmpty()
            //當firstTask爲空時是爲了創建一個沒有任務的線程,再從workQueue中獲取任務,如果workQueue已經爲空,那麼就沒有添加新worker的必要了
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                //workCount
                int wc = workerCountOf(c);
                //如果workCount>=最大線程數容量或者>=core
                //core是傳進來的參數,true代表使用corePoolSize計量,false代表使用maximumPoolSize
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                //如果cas操作將WorkerCount+1成功,直接break外層循環,繼續往下走
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                //重新get ctl
                c = ctl.get();  // Re-read ctl
                //如果runstate變了就要重新從外層循環開始判斷
                if (runStateOf(c) != rs)
                    continue retry;
                //否則走到這裏只能是因爲workerCount變了導致cas失敗,這時重新開始內層循環
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            //new一個worker
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    int rs = runStateOf(ctl.get());
                    //若線程池狀態<SHUTDOWN或
                    // ==SHUTDOWN且是一個空任務
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        //如果線程已經啓動,拋異常
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        //把new worker添加到worker set中
                        workers.add(w);
                        int s = workers.size();
                        //largestPoolSize用來記錄線程池線程數曾達到的最大值
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        //標記worker已添加
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                //標記worker已添加到worker set中,啓動線程標記爲已啓動
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            //如果worker未啓動,進行添加worker失敗的後續處理
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }
  /**
     * Rolls back the worker thread creation.
     * 回滾創建worker線程的操作
     * - removes worker from workers, if present
     * 從worker set移除此worker
     * - decrements worker count
     * worker count遞減
     * - rechecks for termination, in case the existence of this
     *   worker was holding up termination
     *   重新檢查是否要terminate,防止是由於這個回退worker hold住了線程池使其不能停止
     */
    private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null)
                workers.remove(w);
            //循環嘗試,直到cas成功,完成計數-1
            decrementWorkerCount();
            //嘗試停止線程池
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }
 /**
     * Transitions to TERMINATED state if either (SHUTDOWN and pool
     * and queue empty) or (STOP and pool empty).  If otherwise
     * 如果線程池處於SHUTDOWN狀態且線程池及隊列都爲空,或者STOP且線程池爲空,轉換成TERMINATED狀態
     * eligible to terminate but workerCount is nonzero, interrupts an
     * idle worker to ensure that shutdown signals propagate. This
     * 如果符合terminate的條件但workerCount不爲0,則中斷一個空閒worker以保證這個shutdown信號被傳遞
     * method must be called following any action that might make
     * termination possible -- reducing worker count or removing tasks
     * 此方法應該在任何可能導致線程池終止的操作之後被調用,這些操作可能是worker數量被減少或者在shutdown的時候從線程隊列移除了任務
     * from the queue during shutdown. The method is non-private to
     * allow access from ScheduledThreadPoolExecutor.
     * 此方法不是私有的,爲了能夠讓ScheduledThreadPoolExecutor訪問到
     */
    final void tryTerminate() {
        for (;;) {
            int c = ctl.get();
            //c < SHUTDOWN還處於運行狀態
            //或者已經是TIDYING或者TERMINATED狀態了,就無需再tryTerminate
            //或者狀態是SHUTDOWN但工作隊列不爲空,這時候也不能tryTerminate
            if (isRunning(c) ||
                runStateAtLeast(c, TIDYING) ||
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;
            //如果能再往下走,說明處於SHUTDOWN狀態且workQueue是空的
            //如果worker數量不爲0,這時候去中斷一個空閒的worker,即用中斷去喚醒一個阻塞在從workqueue獲取任務的core線程,且只中斷一個
            if (workerCountOf(c) != 0) { // Eligible to terminate
                interruptIdleWorkers(ONLY_ONE);
                return;
            }

            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                //cas將線程池狀態變爲TIDYING,workercount變爲0
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                    try {
                        //如果cas成功了就調用terminated,這裏應該可以看成是一個鉤子方法,本身是個空方法,由子類去override
                        terminated();
                    } finally {
                        //最後把ctl設置成TERMINATED,workercount爲0
                        ctl.set(ctlOf(TERMINATED, 0));
                        //喚醒那些調用了awaitTermination()等待線程池終止的線程
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章