关闭

ThreadPoolExecuter 原理机制

标签: ThreadPoolExecuter线程池多线程
632人阅读 评论(0) 收藏 举报
分类:

当调用 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();

        }

    }


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:121248次
    • 积分:1683
    • 等级:
    • 排名:千里之外
    • 原创:44篇
    • 转载:78篇
    • 译文:2篇
    • 评论:5条
    最新评论