ThreadPoolExecutor源碼解讀

ThreadPoolExecuor是JDK中默認線程池的實現。下面我們對其進入深入剖析。首先來一張類圖

其繼承關係還是很清晰明瞭的,下面從Executor說起,Executor 這個接口只是定義了一個方法executor(Runnable r),用於向線程池提交一個任務。注意到一點這個方法的返回值還是空的。

public interface Executor {

    void execute(Runnable command);
}

ExecutorService 這個接口開始有了線程池的一些雛形,定義了一些線程池的基礎方法如(狀態相關,控制相關),其中比較重要的方法應該是submit(),並且會放回一個Future對象,用於獲取執行結果(是否執行完畢)。同時還允許提交一個Callable對象,結合Future對象使用,可以真實獲取執行的結果,彌補了Runable 對象執行完畢,無法獲得結果的缺陷。後面會對Future及Callable進行深入分析。

public interface ExecutorService extends Executor {

  
    /**
      *  關閉空閒的worker 線程,不會影響執行中的任務
      *
      */


    void shutdown();

    /**
     *  將所有執行中的線程置爲中斷,並返回未執行的任務
     */
    List<Runnable> shutdownNow();

  
    boolean isShutdown();

   
    boolean isTerminated();

    /**
     * 若爲停止狀態則直接返回,否則等待後再判斷返回
     */
    boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;

    /**
     * 
     * 提交一個有返回結果的任務
     */
    <T> Future<T> submit(Callable<T> task);

    /**
     * 提交一個Runnbale對象,以及一個結果
     */ 
    <T> Future<T> submit(Runnable task, T result);

    /**
     * 不解釋
     */
    Future<?> submit(Runnable task);

    /**
     * 批量執行
     */
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;

    /**
     * 
     * 給點的時間內批量執行
     */
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;

    /**
      * 提交一堆任務。其中一個有返回結果就返回。
      *
     */
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;

    /**
      * 給定的時間範圍內,提交一堆任務,其中一個執行完且再時間範圍內就返回,若超時則直接返回
     */
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

接下來再看看AbstractExecutorService 同樣的套路都是實現一些公共的方法。比較關鍵的是實現了submit的那幾個方法。我們來看看。還是挺清晰明瞭的,都是將任務封裝爲一個FutureTask 然後調用execute(Runable command)方法。FutureTask 是啥??我們後面再解釋解釋。

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

  
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

  
    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }

  
    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }


    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    

 

接下來的分析就進入到重頭戲了。ThreadPoolExecutor。先來看看主要的成員變量

    /**
      *  高三位標識線程池狀態,低29位標識線程數量
      *
    * /
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

     /**
       * 阻塞隊列,存放任務
       *
       */
     private final BlockingQueue<Runnable> workQueue;


    /**
      * 鎖對象 進行關鍵操作的時候進行上鎖。
      */
    private final ReentrantLock mainLock = new ReentrantLock();

   /**
     * 存放封裝工作線程的Worker
     */
    private final HashSet<Worker> workers = new HashSet<Worker>();


   /**
     * Wait condition to support awaitTermination
     */
    private final Condition termination = mainLock.newCondition();

   /**
     * Tracks largest attained pool size. Accessed only under
     * mainLock.
     */
    private int largestPoolSize;

  /**
     * Counter for completed tasks. Updated only on termination of
     * worker threads. Accessed only under mainLock.
     */
    private long completedTaskCount;

    /**
      * 線程工廠
      */
    private volatile ThreadFactory threadFactory;

    /**
     * 拒絕策略
     * Handler called when saturated or shutdown in execute.
     */
    private volatile RejectedExecutionHandler handler;

    /**
     * 空閒存活時間
     */
    private volatile long keepAliveTime;

    /**
     * 核心線程數量
     */
    private volatile int corePoolSize;

    /**
     * 最大線程數量
     */
    private volatile int maximumPoolSize;


  

線程池的狀態有以下幾個,存保存在ctl的高三位(通過位移操作 左移表示*2,右移表示除以2)

    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

 

接着分析重要方法

ThreadPoolExecutor的構造方法基本上是由以下幾個參數組成的

   public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

核心線程數,最大線程數,最大空閒時間,時間單位,阻塞隊列,線程工廠,以及拒絕策略

常見的拒絕策略有 

CallerRunsPolicy (直接再提交線程中執行任務)
AbortPolicy (拋異常拒絕)
DiscardPolicy (直接丟棄)
DiscardOldestPolicy (放棄最老的任務,再次提交當前任務)

核心方法

 public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        //線程數量還沒到達核心數量,創建新線程
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        // 線程池正在運行中,且成功將任務放進隊列
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            // 再一次進行檢查,如果非運行狀態就刪除任務,並拒絕
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                // 沒有工作線程就添加一下
                addWorker(null, false);
        }
        // 這裏實際上是放不進阻塞隊列了纔去創建新的工作器,所以對阻塞隊列的設置很關鍵了
        // 要不然工作線程永遠不會達到最大的線程數
        else if (!addWorker(command, false))
            // 未能成功創建線程,就拒絕任務
            reject(command);
    }

再來看看addWorker,addWorker 主要的任務就是創建新的工作線程,其中Worker是ThreadPoolExecutor的一個成員內部類。

我們先來看看這個類,這個類主要就是來執行任務的,所以呢其關鍵成員是持有一個線程對象,其次比較關鍵的是他集成了AQS,一個非常重要的類,下次再對這個類進行分析。

private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        /**
         * This class will never be serialized, but we provide a
         * serialVersionUID to suppress a javac warning.
         */
        private static final long serialVersionUID = 6138294804551838833L;

        /** 真正幹活的線程 */
        final Thread thread;

        /** 該工作器的首個任務,初始化的時候賦予的. */
        Runnable firstTask;
        /** 乾的任務的數量 */
        volatile long completedTasks;

        /**
         * Creates with given first task and thread from ThreadFactory.
         * @param firstTask the first task (null if none)
         */
        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

        /** Delegates main run loop to outer runWorker  */
        public void run() {
            runWorker(this);
        }

        // Lock methods
        //
        // The value 0 represents the unlocked state.
        // The value 1 represents the locked state.

        protected boolean isHeldExclusively() {
            return getState() != 0;
        }

        protected boolean tryAcquire(int unused) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        protected boolean tryRelease(int unused) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        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) {
                }
            }
        }
    }
  private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // 線程是停止的且沒任務傳過來,不用創建新的工作器,直接放回
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                int wc = workerCountOf(c);
                // 是否已經大於核心線程數或者最大線程數
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                // cas 添加工作器數量 並跳出循環添加工作器
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            // 創建工作器
            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());

                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    //啓動線程
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

線程啓動了之後,就會去執行worker 的run方法。其run()實際上是調用ThreadPoolExecutor的runWork(worker)方法。

final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
            // 循環去獲取任務,獲取不到這裏會阻塞,這個方法也是挺關鍵的
            while (task != null || (task = getTask()) != null) {
                w.lock();
                // If pool is stopping, ensure thread is interrupted;
                // if not, ensure thread is not interrupted.  This
                // requires a recheck in second case to deal with
                // shutdownNow race while clearing interrupt
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
                    // 鉤子方法,執行一些前置操作,這裏是空實現
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                        task.run();
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {    
                        // 同樣是空實現
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    //任務數自增
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            // 跳出了循環,可能是線程池關閉。線程等待時間大於最大空閒時間的,關閉該工作線程
            processWorkerExit(w, completedAbruptly);
        }
    }

再來分析一個重要的方法getTask(),爲什麼說其重要呢。因爲它涉及到線程池的一個重要思想,當線程池>coreSize 時或者線程等待時間大於最大空閒時間時,會對線程進行回收操作。

 private Runnable getTask() {
        //是否超時的一個標誌
        boolean timedOut = false; 

        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // 線程池關了。就減少工作器數量
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            //當前的工作線程數量
            int wc = workerCountOf(c);

            // 一個標識,代表需部需要刪線程 如等待時間超時了,有空閒線程之類的
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                // 獲取超時了。
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

線程池狀態演變圖

 

繼續來看看幾個重要的接口及相關實現

Future:用來獲取異步結果主要的方法應該是get()

public interface Future<V> {


    boolean cancel(boolean mayInterruptIfRunning);

  
    boolean isCancelled();


    boolean isDone();


    V get() throws InterruptedException, ExecutionException;

  
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

Callable 能夠獲取結果的任務 

public interface Callable<V> {
 
    V call() throws Exception;
}

在之前我們說過無論提交的Runnbale還是Callable 最終轉化爲的都是FutureTask 。這個FutureTask是個什麼呢?我們來看看類圖

FutureTask 既實現了Runnable 接口也實現了Future接口。有一點需要注意的是在FutureTask中。Runnable 對象也是統一轉化爲Callable對象的。這是怎麼轉換的呢??看看代碼就知道了。簡單滴適配一下而已。下篇文章將對FutureTask進行深入解讀

  static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
    }

 

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