《java.util.concurrent 包源码阅读》12 线程池系列之ThreadPoolExecutor 第二部分

接着说worker线程是如何工作的。ThreadPoolExecutor有一个成员类叫Worker,所起到的作用就是线程池worker线程的作用。

private final class Worker extends AbstractQueuedSynchronizer implements Runnable

这里AbstractQueuedSynchronizer的作用是使Worker具有锁的功能,在执行任务时,会把Worker锁住,这个时候就无法中断Worker。Worker空闲时候是线程池可以通过获取锁,改变Worker的某些状态,在此期间因为锁被占用,Worker就是不会执行任务的。

Worker工作的逻辑在ThreadPoolExecutor#runWorker方法中

        public void run() {
            runWorker(this);
        }

因此转到runWorker方法:

    final void runWorker(Worker w) {
        Runnable task = w.firstTask;
        w.firstTask = null;
        boolean completedAbruptly = true;
        try {
            // 执行分配的任务或者从BlockingQueue中等待获取任务
            while (task != null || (task = getTask()) != null) {
                w.lock();
                clearInterruptsForTaskRun();
                try {
                    // 执行任务之前的工作
                    beforeExecute(w.thread, task);
                    Throwable thrown = null;
                    // 执行任务,如果发生异常,该Worker就不会再继续执行任务
                    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 {
            // Worker不再执行任务的处理,completedAbruptly为false
            // 表示正常结束,否则表示执行任务出错。
            processWorkerExit(w, completedAbruptly);
        }
    }

来看看processWorkerExit,重点看看执行任务发生异常时该如何处理

    private void processWorkerExit(Worker w, boolean completedAbruptly) {
        // 发生异常,首先要更新Worker数量
        if (completedAbruptly)
            decrementWorkerCount();

        // 移除这个Worker
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += w.completedTasks;
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

        // 尝试停止线程池,正常运行的线程池调用该方法不会有任何动作
        tryTerminate();

        int c = ctl.get();
        // 如果线程池没有被关闭的话,
        if (runStateLessThan(c, STOP)) {
            // Worker不是异常退出,检查worker线程数是不是小于最小值
            // 这个最小值分为几种情况:
            // 1. allowCoreThreadTimeOut(JDK6新加)表示是否允许线程池在超
            //     过一定时间没有收到任务后退出,这种情况下,最小值为0,因为如果如
            //     果一直没有任何任务,worker线程数是0
            // 2. 最小值为corePoolSize,因为corePoolSize可能为0,因此这种情况
            //     下,如果有任务的话必然会有Worker,因此最小值为1
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return;
            }
            // 如果Worker线程数小于最小值,新建一个Worker线程
            addWorker(null, false);
        }
    }

 这篇文章主要讲述了Worker线程的工作原理,接下里会讲线程池是如何进行状态切换的。

posted @ 2014-08-15 10:04  梧留柒  阅读(1827)  评论(0编辑  收藏  举报