java原始碼-ThreadPoolExecutor(2)

晴天哥發表於2018-08-23

開篇

 這篇文章的主要目標是為了講解清楚ThreadPoolExecutor的提交任務的過程,非常推薦靜下心來仔細閱讀。
java原始碼-ThreadPoolExecutor(1)
java原始碼-ThreadPoolExecutor(2)
java原始碼-ThreadPoolExecutor(3)

ThreadPoolExecutor狀態介紹

 ThreadPoolExecutor針對執行緒池一共維護了五種狀態,實現上用用高3位表示ThreadPoolExecutor的執行狀態,低29位維持執行緒池執行緒個數,分別是:

  • RUNNING = -1 << COUNT_BITS = -1<<29 高三位為111
  • SHUTDOWN = 0 << COUNT_BITS = 0<<29 高三位為000
  • STOP = 1 << COUNT_BITS = 1<<29 高三位為001
  • TIDYING = 2 << COUNT_BITS = 2<<29 高三位為010
  • TERMINATED = 3 << COUNT_BITS = 3<<29 高三位為011
public class ThreadPoolExecutor extends AbstractExecutorService {
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    // Integer.SIZE=32,Integer.SIZE-3=29,COUNT_BITS=29
    private static final int COUNT_BITS = Integer.SIZE - 3;
    // 執行緒池最大執行緒數=536870911(2^29-1),CAPACITY二進位制中低29為為1,高3位為0
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

    // 用高3位表示ThreadPoolExecutor的執行狀態
    // RUNNING=111
    private static final int RUNNING    = -1 << COUNT_BITS;
    // SHUTDOWN=000
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    // STOP=001
    private static final int STOP       =  1 << COUNT_BITS;
    // TIDYING=010
    private static final int TIDYING    =  2 << COUNT_BITS;
    // TERMINATED=110
    private static final int TERMINATED =  3 << COUNT_BITS;

    // Packing and unpacking ctl
    
    // runStateOf通過獲取高3位來對比
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    // workerCountOf通過比較低29位來獲取執行緒數
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    private static int ctlOf(int rs, int wc) { return rs | wc; }

    private static boolean runStateLessThan(int c, int s) {
        return c < s;
    }

    private static boolean runStateAtLeast(int c, int s) {
        return c >= s;
    }

    private static boolean isRunning(int c) {
        return c < SHUTDOWN;
    }

ThreadPoolExecutor任務提交過程

 ThreadPoolExecutor提交任務程式碼是在AbstractExecutorService當中通過submit()方法實現的,按照兩個步驟來實現:

  • 通過newTaskFor()方法建立待提交任務,該方法內部的實現後面再分析。
  • 通過execute()方法提交task,execute的在ThreadPoolExecutor類中實現重寫。
  • 進一步跟進ThreadPoolExecutor的execute方法
public abstract class AbstractExecutorService implements ExecutorService {

    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的execute其實在原始碼自帶的註釋中已經寫的很清楚了,怕自己翻譯的不是特別所以這次直接把註釋也貼在程式碼當中了,整個過程分為三個過程:

  • 1、當前的執行緒數是否小於corePoolSize,新建core執行緒並執行第一個任務。
  • 2、如果第一步不滿足條件,那麼就把任務提交到workQueue代表的佇列當中。
  • 3、如果第二步不滿足條件,那麼就就新建不屬於corePoolSize計數的執行緒(也就是新建core以外的執行緒)來進行處理。
  • 4、如果都失敗那麼就直接通過rejectHandler拒絕任務,步驟123當中任何檢測到執行緒池關閉的情況直接執行任務拒絕。
public class ThreadPoolExecutor extends AbstractExecutorService {
    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.
         *
         * 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.
         *
         * 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.
         */
        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);
    }
}

  ThreadPoolExecutor的addWorker方法有兩個引數,Runnable firstTask代表待執行任務, boolean core代表是否啟動核心執行緒,整個啟動過程主要分為三個步驟:

  • 前置檢查:檢查執行緒池是否處於關閉狀態,在正常執行的情況下增加工作執行緒計數。
  • 正常處理:建立Worker物件並在加鎖的條件下將新建worker新增到workers集合當中,並通過呼叫t.start()方法啟動執行緒。
  • 後置處理:判斷啟動執行緒是否失敗,如果失敗那麼就嘗試中止執行緒池。
public class ThreadPoolExecutor extends AbstractExecutorService {
    private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                int wc = workerCountOf(c);
                // 判斷是否超出執行緒限制,corePoolSize和core執行緒數,
                // maximumPoolSize代表超出core部分的執行緒數
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                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;
    }

    private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null)
                workers.remove(w);
            decrementWorkerCount();
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }
}

ThreadPoolExecutor的worker介紹

  ThreadPoolExecutor的worker實現Runnable介面,在worker的內部run()方法中通過執行runWorker()方法來啟動task,啟動方式會呼叫task.run()方法,所以從這個角度來看,task的執行執行緒其實ThreadPoolExecutor執行緒池中的worker。

  • Worker類內部包含:Thread thread工作執行緒用於執行task、Runnable firstTask標識待執行任務。
  • runWorker()方法內部負責執行來自提交的firstTask或者阻塞從任務佇列通過getTask()方法取得待執行任務
  • runWorker()方法內部通過執行task.run()負責真正執行任務。
public class ThreadPoolExecutor extends AbstractExecutorService {

    private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        private static final long serialVersionUID = 6138294804551838833L;

        /** Thread this worker is running in.  Null if factory fails. */
        final Thread thread;
        /** Initial task to run.  Possibly null. */
        Runnable firstTask;
        /** Per-thread task counter */
        volatile long completedTasks;

        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);
        }
    }

 runWorker內部主要做兩件事情,分別是:

  • 獲取任務:通過直接傳進來firstTask或者通過getTask從任務佇列中獲取任務
  • 執行任務:task.run()執行真正的task任務
    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()方法外層是一個for迴圈,然後內部從workQueue獲取任務,區分設定超時或者阻塞等待。

  • 阻塞等待直至執行緒獲取到可消費任務。
  • 超時等待使用的是keepAliveTime,用於超時後設定執行緒超時標記然後執行緒退出工作。
  • 執行緒退出迴圈是通過返回task=null,外層迴圈直接結束實現。
    private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

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

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

            // Are workers subject to culling?
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            // 標記執行緒退出工作部分的邏輯,通過返回task=null,從而在外層呼叫方實現退出while迴圈
            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;
            }
        }
    }
}

ThreadPoolExecutor的task介紹

  ThreadPoolExecutor的newTaskFor()方法負責建立task,建立的FutureTask的例項本身實現了Runnable、Future的介面。

  • FutureTask內部可以建立入參為Runnable的物件的時候會建立一個代理器
  • RunnableAdapter,建立入參為Callable的物件就比較直接了。
  • FutureTask的執行函式run()負責執行Callable物件的call()方法並將返回值通過set()方法設定到outcome物件。
  • FutureTask的get()方法負責獲取返回值,就是我們submit()後返回的future的get()呼叫。
public abstract class AbstractExecutorService implements ExecutorService {
    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 class Executors {
    public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
    }

    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;
        }
    }
}




public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}




public class FutureTask<V> implements RunnableFuture<V> {
    /**
     * Possible state transitions:
     * NEW -> COMPLETING -> NORMAL
     * NEW -> COMPLETING -> EXCEPTIONAL
     * NEW -> CANCELLED
     * NEW -> INTERRUPTING -> INTERRUPTED
     */
    private volatile int state;
    private static final int NEW          = 0;
    private static final int COMPLETING   = 1;
    private static final int NORMAL       = 2;
    private static final int EXCEPTIONAL  = 3;
    private static final int CANCELLED    = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED  = 6;

    private Callable<V> callable;
    private Object outcome; // non-volatile, protected by state reads/writes
    private volatile Thread runner;
    private volatile WaitNode waiters;

    private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }

    public boolean isCancelled() {
        return state >= CANCELLED;
    }

    public boolean isDone() {
        return state != NEW;
    }

    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

    public V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (unit == null)
            throw new NullPointerException();
        int s = state;
        if (s <= COMPLETING &&
            (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
            throw new TimeoutException();
        return report(s);
    }

    protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
            finishCompletion();
        }
    }
    
    // 核心的邏輯,負責呼叫物件的call方法並賦值返回值
    public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            runner = null;
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

    // Unsafe mechanics
    private static final sun.misc.Unsafe UNSAFE;
    private static final long stateOffset;
    private static final long runnerOffset;
    private static final long waitersOffset;
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> k = FutureTask.class;
            stateOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("state"));
            runnerOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("runner"));
            waitersOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("waiters"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }

}

參考文章

ThreadPoolExecutor解析-主要原始碼研究
ThreadPoolExecutor(五)——執行緒池關閉相關操作
ThreadPoolExecutor(六)——執行緒池關閉之後


相關文章