ThreadPoolExecuter 原理機制

當調用 execute() 方法添加一個任務時,線程池會做如下判斷:

a. 如果正在運行的線程數量小於 corePoolSize,那麼馬上創建線程運行這個任務;

b. 如果正在運行的線程數量大於或等於 corePoolSize,那麼將這個任務放入隊列。

c. 如果這時候隊列滿了,而且正在運行的線程數量小於 maximumPoolSize,那麼還是要創建線程運行這個任務;

d. 如果隊列滿了,而且正在運行的線程數量大於或等於 maximumPoolSize,那麼線程池會拋出異常,告訴調用者我不能再接受任務了

e.當一個線程完成任務時,它會從隊列中取下一個任務來執行。

f.當一個線程無事可做,超過一定的時間(keepAliveTime)時,線程池會判斷,如果當前運行的線程數大於 corePoolSize,那麼這個線程就被停掉。所以線程池的所有任務完成後,它最終會收縮到 corePoolSize 的大小。

一:Executor 將有限邊界用於最大線程和工作隊列容量飽和:

  1. ThreadPoolExecutor.AbortPolicy 中,處理程序遭到拒絕將拋出運行時RejectedExecutionException
  2. 在 ThreadPoolExecutor.CallerRunsPolicy 中,線程調用運行該任務的execute 本身。此策略提供簡單的反饋控制機制,能夠減緩新任務的提交速度。
  3. 在 ThreadPoolExecutor.DiscardPolicy 中,不能執行的任務將被刪除,不拋出異常。
  4. 在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果執行程序尚未關閉,則位於工作隊列頭部的任務將被刪除,然後重試執行程序(如果再次失敗,則重複此過程)。不拋出異常。

二:線程池異常:
        1)executorService.execute(Runnnable runnable)  通過   t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler())

    public class LufaxThreadFactory implements ThreadFactory {

   private static final ThreadFactory DEFAULT_THREAD_FACTORY = Executors.defaultThreadFactory();

    public LufaxThreadFactory(String module) {

        this.module = module;

    }

    @Override

    public Thread newThread(Runnable r) {

        if (r == nullthrow new NullPointerException();

        Thread t = DEFAULT_THREAD_FACTORY.newThread(r);

        //設置捕獲異常

        t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {

            @Override

            public void uncaughtException(Thread t, Throwable e) {

                Logger.error(this, String.format("Failed to exeute runnable r [module:%s]"module), e);

            }

        });

        return t;

}}

2)executorService.execute(Callable<T> callable)  Future.get()會拋出ExecutionException

線程池 java.util.concurrent.ThreadPoolExecutor 會Catch住所有異常, 當任務執行完成(java.util.concurrent.ExecutorService.submit(Callable))獲取其結果 時(java.util.concurrent.Future.get())會拋出此RuntimeException。

V innerGet() throws InterruptedException, ExecutionException {
    acquireSharedInterruptibly(
0);
    
if (getState() == CANCELLED)
        
throw new CancellationException();
    
if (exception != null)
        
throw new ExecutionException(exception);
    
return result;
}

三:鉤子回調 beforeExecute()和afterExecute() 監控線程

也就是說當我們想線程池 ThreadPoolExecutor(java.util.concurrent.ExecutorService)提交任務時, 如果不理會任務結果(Feture.get()),那麼此異常將被線程池吃掉。

privatevolatileint   corePoolSize//都是volatile變量

ExecutorService service = Executors.newFixedThreadPool(3);//底層ThreadPoolExecutor

publicclass ThreadPoolExecutor extends AbstractExecutorService{}

publicstatic ExecutorService newFixedThreadPool(int nThreads) {

        returnnew ThreadPoolExecutor(nThreads, nThreads,

                                      0L, TimeUnit.MILLISECONDS,

                                      new LinkedBlockingQueue<Runnable>());

}

publicvoid execute(Runnable command) {

        if (command == null)

            thrownew NullPointerException();

//poolSize大於等於corePoolSize時不增加線程,反之(poolSize < corePoolSize)新初始化線程  

        if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {

//線程執行狀態外爲執行,同時可以添加到隊列中  

            if (runState == RUNNING && workQueue.offer(command)) { //入隊列

                if (runState != RUNNING || poolSize == 0)

                    ensureQueuedTaskHandled(command);

            }

            elseif (!addIfUnderMaximumPoolSize(command))//隊列已滿,並且未達到MaxPoolSize繼續啓動線程

                reject(command); // is shutdown or saturated

        }

}

privateboolean addIfUnderCorePoolSize(Runnable firstTask) {

        Thread t = null;

        final ReentrantLock mainLock = this.mainLock;

        mainLock.lock();

        try {

            if (poolSize < corePoolSize && runState == RUNNING)

                t = addThread(firstTask);

        finally {

            mainLock.unlock();

        }

        if (t == null)

            returnfalse;

        t.start();      //啓動線程

        returntrue;

}

 

    private Thread addThread(Runnable firstTask) {

        Worker w = new Worker(firstTask); //Worker包裝Runnable

        Thread t = threadFactory.newThread(w); //生成線程對象Thread

        if (t != null) {

            w.thread = t;

            workers.add(w);

            int nt = ++poolSize;

            if (nt > largestPoolSize)

                largestPoolSize = nt;

        }

        return t;

    }

 

privatefinalclass Worker implements Runnable {

        /**

         * The runLock is acquired and released surrounding each task

         * execution. It mainly protects against interrupts that are

         * intended to cancel the worker thread from instead

         * interrupting the task being run.

         */

        privatefinal ReentrantLock runLock = new ReentrantLock();

 

        /**

         * Initial task to run before entering run loop. Possibly null.

         */

        private Runnable firstTask;

 

        /**

         * Per thread completed task counter; accumulated

         * into completedTaskCount upon termination.

         */

        volatilelongcompletedTasks;

 

        /**

         * Thread this worker is running in.  Acts as a final field,

         * but cannot be set until thread is created.

         */

        Thread thread;

 

        Worker(Runnable firstTask) {

            this.firstTask = firstTask;

        }

    /**

         * Runs a single task between before/after methods.

         */

        privatevoidrunTask(Runnable task) {

            final ReentrantLock runLock = this.runLock;

            runLock.lock();

            try {

                /*

                 * Ensure that unless pool is stopping, this thread

                 * does not have its interrupt set. This requires a

                 * double-check of state in case the interrupt was

                 * cleared concurrently with a shutdownNow -- if so,

                 * the interrupt is re-enabled.

                 */

//當線程池的執行狀態爲關閉等,則執行當前線程的interrupt()操作  

                if (runState < STOP &&

                    Thread.interrupted() &&

                    runState >= STOP)

                    thread.interrupt();

                /*

                 * Track execution state to ensure that afterExecute

                 * is called only if task completed or threw

                 * exception. Otherwise, the caught runtime exception

                 * will have been thrown by afterExecute itself, in

                 * which case we don't want to call it again.

                 */

                boolean ran = false;

                beforeExecute(thread, task);

                try {

                    task.run();

                    ran = true;

                    afterExecute(task, null);

                    ++completedTasks;

                catch (RuntimeException ex) {

                    if (!ran)

                        afterExecute(task, ex);

                    throw ex;

                }

            finally {

                runLock.unlock();

            }

        }

 

        /**

         * Main run loop

         */

        publicvoid run() {

            try {

                Runnable task = firstTask;

                firstTask = null;

//判斷是否存在需要執行的任務  

                while (task != null || (task = getTask()) != null) {

                    runTask(task);

                    task = null;

                }

            finally {

//如果沒有,則將工作線程移除,當poolSize0是則嘗試關閉線程池

                workerDone(this);

            }

        }

    }

 

    /* Utilities for worker thread control */

 

    /**

     * Gets the next task for a worker thread to run.  The general

     * approach is similar to execute() in that worker threads trying

     * to get a task to run do so on the basis of prevailing state

     * accessed outside of locks.  This may cause them to choose the

     * "wrong" action, such as trying to exit because no tasks

     * appear to be available, or entering a take when the pool is in

     * the process of being shut down.  These potential problems are

     * countered by (1) rechecking pool state (in workerCanExit)

     * before giving up, and (2) interrupting other workers upon

     * shutdown, so they can recheck state. All other user-based state

     * changes (to allowCoreThreadTimeOut etc) are OK even when

     * performed asynchronously wrt getTask.

     *

     @return the task

     */

    Runnable getTask() {

        for (;;) {

            try {

                int state = runState;

                if (state > SHUTDOWN)

                    returnnull;

                Runnable r;

                if (state == SHUTDOWN)  // Help drain queue

                    r = workQueue.poll();

//當線程池大於corePoolSize,同時,存在執行超時時間,則等待相應時間,拿出隊列中的線程

                elseif (poolSize > corePoolSize || allowCoreThreadTimeOut)

                    r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);

                else

//阻塞等待隊列中可以取到新線程  

                    r = workQueue.take();

                if (r != null)

                    return r;

//判斷線程池運行狀態,如果大於corePoolSize,或者線程隊列爲空,也或者線程池爲終止的工作線程可以銷燬

                if (workerCanExit()) {

                    if (runState >= SHUTDOWN// Wake up others

                        interruptIdleWorkers();

                    returnnull;

                }

                // Else retry

            catch (InterruptedException ie) {

                // On interruption, re-check runState

            }

        }

    }

 

     /**

     * Performs bookkeeping for an exiting worker thread.

     @param w the worker

     */

 //記錄執行任務數量,將工作線程移除,當poolSize0是則嘗試關閉線程池  

    void workerDone(Worker w) {

        final ReentrantLock mainLock = this.mainLock;

        mainLock.lock();

        try {

            completedTaskCount += w.completedTasks;

            workers.remove(w);

            if (--poolSize == 0)

                tryTerminate();

        finally {

            mainLock.unlock();

        }

    }


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