JDK1.8源码解析之 ThreadPoolExecutor

268 阅读30分钟

前言

  • 一个{@link ExecutorService},它可以使用多个池线程中的一个执行每个提交的任务,通常使用{@link Executors}工厂方法进行配置。
  • 线程池解决了两个不同的问题:
  • 由于减少了每个任务的调用开销,它们通常在执行大量异步任务时可提供改进的性能,
  • 并且它们提供了一种绑定和管理资源(包括线程)的方法,该资源在执行集合的执行时消耗任务。
  • 每个{@code ThreadPoolExecutor}还维护一些基本统计信息,例如已完成任务的数量。
  • 为了在广泛的上下文中有用,此类提供了许多可调整的参数和可扩展性挂钩。
  • 但是,强烈建议程序员使用更方便的{@link Executors}工厂方法{@link Executors#newCachedThreadPool}(无边界线程池,自动回收),
  • {@link Executors#newFixedThreadPool}(固定大小的线程池)
  • 和{ @link Executors#newSingleThreadExecutor}(单个后台线程),
  • 可以为最常见的使用场景预配置设置。否则,在手动配置和调整此类时,请使用以下指南:
  • 核心和最大池大小
  • {@code ThreadPoolExecutor}将根据corePoolSize(请参阅{@link #getCorePoolSize})和maximumPoolSize(请参阅{@link# getMaximumPoolSize})。
  • 当在方法{@link #execute(Runnable)}中提交新任务,并且正在运行的线程少于corePoolSize线程时,
  • 即使其他工作线程处于空闲状态,也会创建一个新线程来处理请求。
  • 如果运行的线程数大于corePoolSize但小于maximumPoolSize,则仅在队列已满时才创建新线程。
  • 通过将corePoolSize和maximumPoolSize设置为相同,可以创建固定大小的线程池。
  • 通过将maximumPoolSize设置为本质上不受限制的值,例如{@code Integer.MAX_VALUE},可以允许池容纳任意数量的并发任务。
  • 通常,核心和最大池大小仅在构造时设置,但也可以使用{@link #setCorePoolSize}和{@link #setMaximumPoolSize}动态更改。
  • 按需构建
  • 默认情况下,甚至只有在有新任务到达时才开始甚至启动核心线程,
  • 但是可以使用方法{@link #prestartCoreThread}或{@link #prestartAllCoreThreads}动态地覆盖它。
  • 如果使用非空队列构造池,则可能要预启动线程。
  • 创建新线程
  • 使用{@link ThreadFactory}创建新线程。
  • 如果没有另外指定,则使用{@link Executors#defaultThreadFactory},
  • 该线程创建的线程全部位于相同的{@link ThreadGroup}中,并且具有相同的{@code NORM_PRIORITY}优先级和非守护进程状态。
  • 通过提供不同的ThreadFactory,可以更改线程的名称,线程组,优先级,守护程序状态等。
  • 如果{@code ThreadFactory}在通过从{@code newThread}返回null时被要求创建线程失败,执行者将继续,但可能无法执行任何任务。
  • 线程应具有“ modifyThread” {@code RuntimePermission}。
  • 如果使用该池的工作线程或其他线程不具有此许可权,则服务可能会降级:配置更改可能不会及时生效,
  • 并且关闭池可能保持在可能终止但未完成的状态。
  • 存活时间
  • 如果当前池中的线程数超过corePoolSize,则多余的线程将在空闲时间超过keepAliveTime时终止
  • (请参阅{@link #getKeepAliveTime(TimeUnit)})。
  • 当未积极使用池时,这提供了减少资源消耗的方法。
  • 如果池稍后变得更加活动,则将构建新线程。
  • 也可以使用方法{@link #setKeepAliveTime(long,TimeUnit)}动态更改此参数。
  • 使用{@code Long.MAX_VALUE}的值{@link TimeUnit#NANOSECONDS}有效地使空闲线程永远不会在关闭之前终止。
  • 默认情况下,仅当存在多个corePoolSize线程时,保持活动策略才适用。
  • 但是方法{@link #allowCoreThreadTimeOut(boolean)}也可以用于将此超时策略应用于核心线程,只要keepAliveTime值不为零即可。
  • 排队
  • 任何{@link BlockingQueue}均可用于传输和保留提交的任务。此队列的使用与池大小交互:
  • 如果正在运行的线程少于corePoolSize线程,则执行程序总是喜欢添加新线程,而不是排队。
  • 如果正在运行corePoolSize或更多线程,则执行程序总是更喜欢对请求进行排队,而不是添加新线程。
  • 如果无法将请求排队,则将创建一个新线程,除非该线程超过了maximumPoolSize,在这种情况下,该任务将被拒绝。
  • 有三种一般的排队策略:
  • 直接交接。 {@link SynchronousQueue}是工作队列的一个很好的默认选择,它可以将任务移交给线程,而不必另外保留它们。
  • 在这里,如果没有立即可用的线程来运行任务,则尝试将任务排队的尝试将失败,因此将构造一个新线程。
  • 在处理可能具有内部依赖性的请求集时,此策略避免了锁定。直接切换通常需要无限制的maximumPoolSizes,以避免拒绝新提交的任务。
  • 反过来,当平均而言,命令继续以比其处理速度更快的速度到达时,这可能会带来无限线程增长的可能性。
  • 无限队列。当所有corePoolSize线程都忙时,使用无限制的队列(例如,没有预定义容量的{@link LinkedBlockingQueue})将导致新任务在队列中等待。
  • 因此,将只创建corePoolSize线程。
  • (因此,maximumPoolSize的值没有任何作用。)当每个任务完全独立于其他任务时,这可能是适当的,因此任务不会影响彼此的执行。
  • 例如,在网页服务器中。
  • 尽管这种排队方式对于消除短暂的请求突发很有用,但是它承认当命令平均到达的速度比处理命令的速度快时,工作队列就会无限增长。
  • 有界队列。当与有限的maximumPoolSizes一起使用时,有界队列(例如,{@link ArrayBlockingQueue})有助于防止资源耗尽,
  • 但是调优和控制起来会更加困难。队列大小和最大池大小可能会相互折衷:
  • 使用大队列和小池可以最大程度地减少CPU使用率,操作系统资源和上下文切换开销,但可能导致人为降低吞吐量。
  • 如果任务频繁阻塞(例如,如果它们受I /O限制),则系统可能能够安排比您原先允许的线程更多的时间。
  • 使用小队列通常需要更大的池大小,这会使CPU繁忙,但可能会遇到无法接受的调度开销,这也会降低吞吐量。
  • 拒绝任务
  • 当执行器已关闭,并且执行器对最大线程数和工作队列容量使用有限范围且已饱和时,
  • 在方法{@link #execute(Runnable)}中提交的新任务将被拒绝。
  • 无论哪种情况,{@code execute}方法都将调用其{@link RejectedExecutionHandler}的{@link RejectedExecutionHandler#rejectedExecution(Runnable,ThreadPoolExecutor)}方法。
  • 提供了四个预定义的处理程序策略:
  • 在默认的{@link ThreadPoolExecutor.AbortPolicy}中,处理程序在拒绝时抛出运行时{@link RejectedExecutionException}。
  • 在{@link ThreadPoolExecutor.CallerRunsPolicy}中,调用{@code execute}的线程本身运行任务。这提供了一种简单的反馈控制机制,将降低新任务提交的速度。
  • 在{@link ThreadPoolExecutor.DiscardPolicy}中,简单地删除了无法执行的任务。
  • 在{@link ThreadPoolExecutor.DiscardOldestPolicy}中,如果未关闭执行程序,则将丢弃工作队列开头的任务,然后重试执行(该操作可能再次失败,导致重复执行此操作。)
  • 可以定义和使用其他类型的{@link RejectedExecutionHandler}类。
  • 这样做需要格外小心,尤其是在设计策略仅在特定容量或排队策略下工作时。
  • 挂钩方法
  • 此类提供{@code protected}可重写的{@link #beforeExecute(Thread,Runnable)}和{@link #afterExecute(Runnable,Throwable)}方法,这些方法在每个任务执行前后被调用。
  • 这些可以用来操纵执行环境。例如,重新初始化ThreadLocals,收集统计信息或添加日志条目。
  • 此外,一旦执行程序完全终止,方法{@link #terminated}可以被覆盖以执行需要执行的任何特殊处理。
  • 如果钩子或回调方法引发异常,内部工作线程可能进而失败并突然终止。
  • 队列维护
  • 方法{@link #getQueue()}允许访问工作队列,以进行监视和调试。
  • 强烈建议不要将此方法用于任何其他目的。
  • 当取消大量排队的任务时,可以使用提供的两种方法{@link #remove(Runnable)}和{@link #purge}来辅助存储回收。
  • Finalization
  • 程序中不再引用且没有剩余线程的池将自动{@code shutdown}。
  • 如果您即使在用户忘记调用{@link #shutdown}的情况下也要确保收回未引用的池,
  • 则必须通过使用零核心线程的下限来设置适当的保活时间,
  • 以安排未使用的线程最终死掉和/或设置{@link #allowCoreThreadTimeOut(boolean)}。

源码

package java.util.concurrent;

public class ThreadPoolExecutor extends AbstractExecutorService {
    /**
     * 主池控制状态ctl是一个原子整数,打包了两个概念字段
     * workerCount,指示了线程的有效数量
     * runState,指示了是否运行,关闭等。
     * 为了将它们打包为一个int,我们将workerCount限制为(2 ^ 29 )-1(大约5亿)个线程,
     * 而不是(2 ^ 31)-1(20亿)可以表示的线程。
     * 如果将来有问题,可以将该变量更改为AtomicLong,并在以下调整shift /mask常数。
     * 但是在需要之前,使用int可以使此代码更快,更简单。
     * workerCount是已被允许启动但不允许停止的工人数。
     * 该值可能与活动线程的实际数量暂时不同,
     * 例如,当ThreadFactory在被询问时未能创建线程,并且退出线程仍在终止之前执行簿记操作时,该值会有所不同。
     * 用户可见池大小报告为工作集的当前大小。
     * runState提供主要的生命周期控制,并具有以下值:
     * RUNNING:接受新任务并处理排队的任务
     * SHUTDOWN:不接受新任务,但处理排队的任务
     * STOP:不接受新任务,不处理排队的任务,并中断进行中的任务
     * TIDYING:所有任务都已终止,workerCount为零,线程转换到
     * TIDYING状态将运行Terminated()挂钩方法
     * TERMINATED:terminald()已完成这些值之间的数字顺序很重要,可以进行有序比较。
     * runState随时间单调增加,但不必达到每个状态。
     * RUNNING-> SHUTDOWN在调用shutdown()时,可能隐式在finalize()中
     * (RUNNING或SHUTDOWN)-> STOP在调用shutdownNow()时
     * SHUTDOWN-> TIDYING当队列和池都为空时
     * STOP-> TIDYING当池为空时
     * TIDYING-> TERMINATED当Terminated()挂钩方法完成时
     * 状态达到TERMINATED时,在awaitTermination()中等待的线程将返回。
     * 检测从SHUTDOWN到TIDYING的转换并不像您想要的那样简单,因为在SHUTDOWN状态期间队列在非空之后可能会变空,反之亦然,
     * 但是只有在看到它为空之后,我们看到workerCount为0(有时需要重新检查-参见下文)。
     */
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    private static final int COUNT_BITS = Integer.SIZE - 3;
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

    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;

    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    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;
    }

    private boolean compareAndIncrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect + 1);
    }

    private boolean compareAndDecrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect - 1);
    }

    private void decrementWorkerCount() {
        do {} while (! compareAndDecrementWorkerCount(ctl.get()));
    }

    private final BlockingQueue<Runnable> workQueue;

    private final ReentrantLock mainLock = new ReentrantLock();

    private final HashSet<Worker> workers = new HashSet<Worker>();

    private final Condition termination = mainLock.newCondition();

    private int largestPoolSize;

    private long completedTaskCount;

    /**
     * 新线程的工厂。使用此工厂(通过方法addWorker)创建所有线程。必须为所有调用程序做好准备,以使addWorker失败,这可能反映出系统或用户的策略限制了线程数。即使未将其视为错误,创建线程的失败也可能导致新任务被拒绝或现有任务仍停留在队列中。我们走得更远,即使遇到诸如OutOfMemoryError之类的错误,它们也会保留池不变式,而在尝试创建线程时可能会抛出该错误。由于需要在Thread.start中分配本机堆栈,因此此类错误相当常见,并且用户将需要执行清理池关闭来进行清理。可能有足够的可用内存来完成清除代码,而不会遇到另一个OutOfMemoryError。 
     */
    private volatile ThreadFactory threadFactory;

    private volatile RejectedExecutionHandler handler;

    private volatile long keepAliveTime;

    private volatile boolean allowCoreThreadTimeOut;

    private volatile int corePoolSize;

    private volatile int maximumPoolSize;

    private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

    private static final RuntimePermission shutdownPerm =
        new RuntimePermission("modifyThread");

    private final AccessControlContext acc;

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

        final Thread thread;
        Runnable firstTask;
        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);
        }
        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 void advanceRunState(int targetState) {
        for (;;) {
            int c = ctl.get();
            if (runStateAtLeast(c, targetState) ||
                ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                break;
        }
    }

    final void tryTerminate() {
        for (;;) {
            int c = ctl.get();
            if (isRunning(c) ||
                runStateAtLeast(c, TIDYING) ||
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;
            if (workerCountOf(c) != 0) {
                interruptIdleWorkers(ONLY_ONE);
                return;
            }

            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                    try {
                        terminated();
                    } finally {
                        ctl.set(ctlOf(TERMINATED, 0));
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                mainLock.unlock();
            }
        }
    }

    private void checkShutdownAccess() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkPermission(shutdownPerm);
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                for (Worker w : workers)
                    security.checkAccess(w.thread);
            } finally {
                mainLock.unlock();
            }
        }
    }

    /**
     * Interrupts all threads, even if active. Ignores SecurityExceptions
     * (in which case some threads may remain uninterrupted).
     */
    private void interruptWorkers() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers)
                w.interruptIfStarted();
        } finally {
            mainLock.unlock();
        }
    }

    private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }

    private void interruptIdleWorkers() {
        interruptIdleWorkers(false);
    }

    private static final boolean ONLY_ONE = true;

    final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

    void onShutdown() {
    }

    final boolean isRunningOrShutdown(boolean shutdownOK) {
        int rs = runStateOf(ctl.get());
        return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
    }

    private List<Runnable> drainQueue() {
        BlockingQueue<Runnable> q = workQueue;
        ArrayList<Runnable> taskList = new ArrayList<Runnable>();
        q.drainTo(taskList);
        if (!q.isEmpty()) {
            for (Runnable r : q.toArray(new Runnable[0])) {
                if (q.remove(r))
                    taskList.add(r);
            }
        }
        return taskList;
    }

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

    private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly)
            decrementWorkerCount();

        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)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return;
            }
            addWorker(null, false);
        }
    }

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

    /**
     * 
     * 主工作者运行循环。反复从队列中获取任务并执行它们,同时解决许多问题:
     * 1.我们可以从初始任务开始,在这种情况下,我们不需要获取第一个任务。
     * 否则,只要池正在运行,我们就会从getTask获取任务。
     * 如果返回null,则工作程序会由于更改的池状态或配置参数而退出。
     * 其他退出是由于外部代码中的异常引发而导致的,在这种情况下,completedAbruptly成立,
     * 这通常导致processWorkerExit替换此线程。 
     * 2.在运行任何任务之前,先获取锁,以防止任务执行时其他池中断,然后确保除非池正在停止,
     * 否则此线程不会设置其中断。 
     * 3.每个任务运行之前都会调用beforeExecute,这可能会引发异常,在这种情况下,
     * 我们将导致线程死掉(中断,带有completelyAbruptly true的循环),而不处理该任务。 
     * 4.假设beforeExecute正常完成,我们运行任务,收集其引发的任何异常以发送给afterExecute。
     * 我们分别处理RuntimeException,Error(规范保证我们可以捕获它们)和任意Throwables。
     * 因为我们无法在Throwables.run中抛出Throwable,
     * 所以我们将它们包装在Errors中(输出到线程的UncaughtExceptionHandler)。
     * 任何抛出的异常也会保守地导致线程死亡。 
     * 5. task.run完成后,我们调用afterExecute,这也可能引发异常,这也将导致线程死亡。
     * 根据JLS Sec 14.20,此异常是即使task.run抛出也会生效的异常。
     * 异常机制的最终结果是afterExecute和线程的UncaughtExceptionHandler具有与我们所能提供的有关用户代码遇到的任何问题的准确信息。
     * @param w the worker
     */
    final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock();
        boolean completedAbruptly = true;
        try {
            while (task != null || (task = getTask()) != null) {
                w.lock();
                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);
        }
    }

    // Public constructors and methods

    /**
     * 使用给定的初始参数,默认线程工厂和拒绝的执行处理程序创建一个新的{@code ThreadPoolExecutor}。
     * 使用{@link Executors}工厂方法之一而不是此通用构造函数可能会更方便。
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

    /**
     * 使用给定的初始参数和默认的拒绝执行处理程序创建一个新的{@code ThreadPoolExecutor}。
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

    /**
     * 使用给定的初始参数和默认线程工厂创建一个新的{@code ThreadPoolExecutor}。
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

    /**
     * 使用给定的初始参数创建一个新的{@code ThreadPoolExecutor}。
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

    /**
     * Executes the given task sometime in the future.  The task
     * may execute in a new thread or in an existing pooled thread.
     *
     * If the task cannot be submitted for execution, either because this
     * executor has been shutdown or because its capacity has been reached,
     * the task is handled by the current {@code RejectedExecutionHandler}.
     *
     * 在将来的某个时间执行给定的任务。
     * 该任务可以在新线程或现有池线程中执行。
     * 如果由于该执行器已关闭或已达到其容量而无法提交执行任务,
     * 则该任务由当前的{@code RejectedExecutionHandler}处理。
     *
     * @param command the task to execute
     * @throws RejectedExecutionException at discretion of
     *         {@code RejectedExecutionHandler}, if the task
     *         cannot be accepted for execution
     * @throws NullPointerException if {@code command} is null
     */
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * 分3个步骤进行:
         * 1.如果运行的线程少于corePoolSize线程,请尝试使用给定命令作为其第一个任务来启动新线程。对addWorker的调用从原子上检查runState和workerCount,从而通过返回false来防止在不应该添加线程的情况下发出错误警报。 
         * 2.如果一个任务可以成功排队,那么我们仍然需要仔细检查是否应该添加一个线程(因为现有线程自上次检查后就死了)或该池自进入此方法后就关闭了。因此,我们重新检查状态,并在必要时回滚排队(如果已停止),或者在没有线程的情况下启动新线程。 
         * 3.如果我们无法将任务排队,则尝试添加一个新线程。如果失败,我们知道我们已关闭或已饱和,因此拒绝该任务。
         */
        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);
    }

    /**
     * Initiates an orderly shutdown in which previously submitted
     * tasks are executed, but no new tasks will be accepted.
     * Invocation has no additional effect if already shut down.
     *
     * <p>This method does not wait for previously submitted tasks to
     * complete execution.  Use {@link #awaitTermination awaitTermination}
     * to do that.
     * 启动有序关闭,在该关闭中执行先前提交的任务,但不接受任何新任务。
     * 如果已关闭,则调用不会产生任何其他影响。
     * 此方法不等待先前提交的任务完成执行。
     * 使用{@link #awaitTermination awaitTermination}可以做到这一点。
     *
     * @throws SecurityException {@inheritDoc}
     */
    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(SHUTDOWN);
            interruptIdleWorkers();
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }

    /**
     * Attempts to stop all actively executing tasks, halts the
     * processing of waiting tasks, and returns a list of the tasks
     * that were awaiting execution. These tasks are drained (removed)
     * from the task queue upon return from this method.
     *
     * <p>This method does not wait for actively executing tasks to
     * terminate.  Use {@link #awaitTermination awaitTermination} to
     * do that.
     *
     * <p>There are no guarantees beyond best-effort attempts to stop
     * processing actively executing tasks.  This implementation
     * cancels tasks via {@link Thread#interrupt}, so any task that
     * fails to respond to interrupts may never terminate.
     *
     * 尝试停止所有正在执行的任务,中止正在等待的任务的处理,并返回正在等待执行的任务的列表。
     * 从此方法返回后,将从任务队列中清空(删除)这些任务。
     * 此方法不等待主动执行的任务终止。
     * 使用{@link #awaitTermination awaitTermination}可以做到这一点。
     * 除了尽最大努力阻止停止处理正在执行的任务之外,没有任何保证。
     * 此实现通过{@link Thread#interrupt}取消任务,因此任何无法响应中断的任务都可能永远不会终止。
     *
     * @throws SecurityException {@inheritDoc}
     */
    public List<Runnable> shutdownNow() {
        List<Runnable> tasks;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(STOP);
            interruptWorkers();
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
        return tasks;
    }

    public boolean isShutdown() {
        return ! isRunning(ctl.get());
    }

    /**
     * 如果此执行程序正在{@link #shutdown}或{@link #shutdownNow}之后终止,但尚未完全终止,则返回true。
     * 此方法可能对调试有用。
     * 在关闭后足够长的时间内报告返回{@code true}可能表明所提交的任务已被忽略或抑制了中断,从而导致该执行程序无法正确终止。
     */
    public boolean isTerminating() {
        int c = ctl.get();
        return ! isRunning(c) && runStateLessThan(c, TERMINATED);
    }

    public boolean isTerminated() {
        return runStateAtLeast(ctl.get(), TERMINATED);
    }

    public boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (;;) {
                if (runStateAtLeast(ctl.get(), TERMINATED))
                    return true;
                if (nanos <= 0)
                    return false;
                nanos = termination.awaitNanos(nanos);
            }
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Invokes {@code shutdown} when this executor is no longer
     * referenced and it has no threads.
     */
    protected void finalize() {
        SecurityManager sm = System.getSecurityManager();
        if (sm == null || acc == null) {
            shutdown();
        } else {
            PrivilegedAction<Void> pa = () -> { shutdown(); return null; };
            AccessController.doPrivileged(pa, acc);
        }
    }

    /**
     * Sets the thread factory used to create new threads.
     *
     * @param threadFactory the new thread factory
     * @throws NullPointerException if threadFactory is null
     * @see #getThreadFactory
     */
    public void setThreadFactory(ThreadFactory threadFactory) {
        if (threadFactory == null)
            throw new NullPointerException();
        this.threadFactory = threadFactory;
    }

    /**
     * Returns the thread factory used to create new threads.
     * 返回用于创建新线程的线程工厂。
     * @return the current thread factory
     * @see #setThreadFactory(ThreadFactory)
     */
    public ThreadFactory getThreadFactory() {
        return threadFactory;
    }

    /**
     * Sets a new handler for unexecutable tasks.
     * 为无法执行的任务设置新的handler。
     * @param handler the new handler
     * @throws NullPointerException if handler is null
     * @see #getRejectedExecutionHandler
     */
    public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
        if (handler == null)
            throw new NullPointerException();
        this.handler = handler;
    }

    /**
     * Returns the current handler for unexecutable tasks.
     * 返回无法执行任务的当前处理程序。
     *
     * @return the current handler
     * @see #setRejectedExecutionHandler(RejectedExecutionHandler)
     */
    public RejectedExecutionHandler getRejectedExecutionHandler() {
        return handler;
    }

    /**
     * 设置核心线程数。
     * 这将覆盖构造函数中设置的任何值。
     * 如果新值小于当前值,则多余的现有线程将在下次空闲时终止。
     * 如果更大,将在需要时启动新线程来执行任何排队的任务。
     */
    public void setCorePoolSize(int corePoolSize) {
        if (corePoolSize < 0)
            throw new IllegalArgumentException();
        int delta = corePoolSize - this.corePoolSize;
        this.corePoolSize = corePoolSize;
        if (workerCountOf(ctl.get()) > corePoolSize)
            interruptIdleWorkers();
        else if (delta > 0) {
            int k = Math.min(delta, workQueue.size());
            while (k-- > 0 && addWorker(null, true)) {
                if (workQueue.isEmpty())
                    break;
            }
        }
    }

    /**
     * Returns the core number of threads.
     * 返回线程的核心数量。
     * @return the core number of threads
     * @see #setCorePoolSize
     */
    public int getCorePoolSize() {
        return corePoolSize;
    }

    /**
     * Starts a core thread, causing it to idly wait for work. This
     * overrides the default policy of starting core threads only when
     * new tasks are executed. This method will return {@code false}
     * if all core threads have already been started.
     *
     * 启动一个核心线程,使其闲置地等待工作。
     * 这将覆盖仅在执行新任务时启动核心线程的默认策略。
     * 如果所有核心线程均已启动,则此方法将返回{@code false}。
     *
     * @return {@code true} if a thread was started
     */
    public boolean prestartCoreThread() {
        return workerCountOf(ctl.get()) < corePoolSize &&
            addWorker(null, true);
    }

    /**
     * Same as prestartCoreThread except arranges that at least one
     * thread is started even if corePoolSize is 0.
     * 与prestartCoreThread相同,即使corePoolSize为0至少启动一个线程。
     */
    void ensurePrestart() {
        int wc = workerCountOf(ctl.get());
        if (wc < corePoolSize)
            addWorker(null, true);
        else if (wc == 0)
            addWorker(null, false);
    }

    /**
     * Starts all core threads, causing them to idly wait for work. This
     * overrides the default policy of starting core threads only when
     * new tasks are executed.
     *
     * 启动所有核心线程,使它们空闲地等待工作。
     * 这将覆盖仅在执行新任务时启动核心线程的默认策略。
     *
     * @return the number of threads started
     */
    public int prestartAllCoreThreads() {
        int n = 0;
        while (addWorker(null, true))
            ++n;
        return n;
    }

    /**
     * Returns true if this pool allows core threads to time out and
     * terminate if no tasks arrive within the keepAlive time, being
     * replaced if needed when new tasks arrive. When true, the same
     * keep-alive policy applying to non-core threads applies also to
     * core threads. When false (the default), core threads are never
     * terminated due to lack of incoming tasks.
     *
     * 如果此池允许核心线程超时并在keepAlive时间内没有任务到达时终止,则返回true,
     * 如果有新任务到达,则在需要时替换该线程。
     * 如果为true,则适用于非核心线程的相同的保持活动策略也适用于核心线程。
     * 如果为false(默认值),则由于缺少传入任务,核心线程永远不会终止。
     *
     * @return {@code true} if core threads are allowed to time out,
     *         else {@code false}
     *
     * @since 1.6
     */
    public boolean allowsCoreThreadTimeOut() {
        return allowCoreThreadTimeOut;
    }

    /**
     * Sets the policy governing whether core threads may time out and
     * terminate if no tasks arrive within the keep-alive time, being
     * replaced if needed when new tasks arrive. When false, core
     * threads are never terminated due to lack of incoming
     * tasks. When true, the same keep-alive policy applying to
     * non-core threads applies also to core threads. To avoid
     * continual thread replacement, the keep-alive time must be
     * greater than zero when setting {@code true}. This method
     * should in general be called before the pool is actively used.
     *
     * 设置策略,以控制在保持活动时间内没有任务到达时核心线程是否可能超时并终止,并在新任务到达时根据需要替换。
     * 如果为false,则由于缺少传入任务,核心线程永远不会终止。
     * 如果为true,则适用于非核心线程的相同的保持活动策略也适用于核心线程。
     * 为避免连续替换线程,设置{@code true}时,保持活动时间必须大于零。
     * 通常应在主动使用池之前调用此方法。
     *
     * @param value {@code true} if should time out, else {@code false}
     * @throws IllegalArgumentException if value is {@code true}
     *         and the current keep-alive time is not greater than zero
     *
     * @since 1.6
     */
    public void allowCoreThreadTimeOut(boolean value) {
        if (value && keepAliveTime <= 0)
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        if (value != allowCoreThreadTimeOut) {
            allowCoreThreadTimeOut = value;
            if (value)
                interruptIdleWorkers();
        }
    }

    /**
     * Sets the maximum allowed number of threads. This overrides any
     * value set in the constructor. If the new value is smaller than
     * the current value, excess existing threads will be
     * terminated when they next become idle.
     * 设置允许的最大线程数。这将覆盖构造函数中设置的任何值。
     * 如果新值小于当前值,则多余的现有线程将在下次空闲时终止。
     *
     * @param maximumPoolSize the new maximum
     * @throws IllegalArgumentException if the new maximum is
     *         less than or equal to zero, or
     *         less than the {@linkplain #getCorePoolSize core pool size}
     * @see #getMaximumPoolSize
     */
    public void setMaximumPoolSize(int maximumPoolSize) {
        if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
            throw new IllegalArgumentException();
        this.maximumPoolSize = maximumPoolSize;
        if (workerCountOf(ctl.get()) > maximumPoolSize)
            interruptIdleWorkers();
    }

    /**
     * Returns the maximum allowed number of threads.
     * 返回允许的最大线程数。
     * @return the maximum allowed number of threads
     * @see #setMaximumPoolSize
     */
    public int getMaximumPoolSize() {
        return maximumPoolSize;
    }

    /**
     * Sets the time limit for which threads may remain idle before
     * being terminated.  If there are more than the core number of
     * threads currently in the pool, after waiting this amount of
     * time without processing a task, excess threads will be
     * terminated.  This overrides any value set in the constructor.
     * 设置线程在终止之前可能保持空闲的时间限制。
     * 如果当前池中的线程数超过核心数,则在等待此时间而不处理任务之后,多余的线程将被终止。
     * 这将覆盖构造函数中设置的任何值。
     *
     * @param time the time to wait.  A time value of zero will cause
     *        excess threads to terminate immediately after executing tasks.
     * @param unit the time unit of the {@code time} argument
     * @throws IllegalArgumentException if {@code time} less than zero or
     *         if {@code time} is zero and {@code allowsCoreThreadTimeOut}
     * @see #getKeepAliveTime(TimeUnit)
     */
    public void setKeepAliveTime(long time, TimeUnit unit) {
        if (time < 0)
            throw new IllegalArgumentException();
        if (time == 0 && allowsCoreThreadTimeOut())
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        long keepAliveTime = unit.toNanos(time);
        long delta = keepAliveTime - this.keepAliveTime;
        this.keepAliveTime = keepAliveTime;
        if (delta < 0)
            interruptIdleWorkers();
    }

    /**
     * Returns the thread keep-alive time, which is the amount of time
     * that threads in excess of the core pool size may remain
     * idle before being terminated.
     *
     * 返回线程保持活动时间,该时间是超过核心池大小的线程在被终止之前可能保持空闲的时间。
     *
     * @param unit the desired time unit of the result
     * @return the time limit
     * @see #setKeepAliveTime(long, TimeUnit)
     */
    public long getKeepAliveTime(TimeUnit unit) {
        return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
    }

    /* User-level queue utilities */

    /**
     * Returns the task queue used by this executor. Access to the
     * task queue is intended primarily for debugging and monitoring.
     * This queue may be in active use.  Retrieving the task queue
     * does not prevent queued tasks from executing.
     * 返回此执行程序使用的任务队列。
     * 访问任务队列主要用于调试和监视。
     * 该队列可能正在使用中。检索任务队列不会阻止排队的任务执行。
     *
     * @return the task queue
     */
    public BlockingQueue<Runnable> getQueue() {
        return workQueue;
    }

    /**
     * 如果执行程序的内部队列中存在此任务,则将其删除,如果尚未启动,则导致该任务无法运行。
     * 此方法可能可用作取消方案的一部分。
     * 在放入内部队列之前,它可能无法删除已转换为其他形式的任务。
     * 例如,使用{@code Submit}输入的任务可能会转换为保持{@code Future}状态的表单。
     * 但是,在这种情况下,可以使用方法{@link #purge}删除已取消的那些期货。
     *
     * @param task the task to remove
     * @return {@code true} if the task was removed
     */
    public boolean remove(Runnable task) {
        boolean removed = workQueue.remove(task);
        tryTerminate(); // In case SHUTDOWN and now empty
        return removed;
    }

    /**
     * Tries to remove from the work queue all {@link Future}
     * tasks that have been cancelled. This method can be useful as a
     * storage reclamation operation, that has no other impact on
     * functionality. Cancelled tasks are never executed, but may
     * accumulate in work queues until worker threads can actively
     * remove them. Invoking this method instead tries to remove them now.
     * However, this method may fail to remove tasks in
     * the presence of interference by other threads.
     *
     * 尝试从工作队列中删除所有已取消的{@link Future}任务。
     * 此方法可用作存储回收操作,对功能没有其他影响。
     * 已取消的任务永远不会执行,但可能会在工作队列中累积,直到工作线程可以主动将其删除为止。
     * 而是调用此方法尝试立即将其删除。但是,如果存在其他线程的干扰,此方法可能无法删除任务。
     *
     */
    public void purge() {
        final BlockingQueue<Runnable> q = workQueue;
        try {
            Iterator<Runnable> it = q.iterator();
            while (it.hasNext()) {
                Runnable r = it.next();
                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
                    it.remove();
            }
        } catch (ConcurrentModificationException fallThrough) {
            // Take slow path if we encounter interference during traversal.
            // Make copy for traversal and call remove for cancelled entries.
            // The slow path is more likely to be O(N*N).
            for (Object r : q.toArray())
                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
                    q.remove(r);
        }

        tryTerminate(); // In case SHUTDOWN and now empty
    }

    /* Statistics */

    /**
     * Returns the current number of threads in the pool.
     *
     * @return the number of threads
     */
    public int getPoolSize() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // Remove rare and surprising possibility of
            // isTerminated() && getPoolSize() > 0
            return runStateAtLeast(ctl.get(), TIDYING) ? 0
                : workers.size();
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Returns the approximate number of threads that are actively
     * executing tasks.
     *
     * @return the number of threads
     */
    public int getActiveCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            int n = 0;
            for (Worker w : workers)
                if (w.isLocked())
                    ++n;
            return n;
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Returns the largest number of threads that have ever
     * simultaneously been in the pool.
     *
     * @return the number of threads
     */
    public int getLargestPoolSize() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            return largestPoolSize;
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Returns the approximate total number of tasks that have ever been
     * scheduled for execution. Because the states of tasks and
     * threads may change dynamically during computation, the returned
     * value is only an approximation.
     *
     * @return the number of tasks
     */
    public long getTaskCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            long n = completedTaskCount;
            for (Worker w : workers) {
                n += w.completedTasks;
                if (w.isLocked())
                    ++n;
            }
            return n + workQueue.size();
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Returns the approximate total number of tasks that have
     * completed execution. Because the states of tasks and threads
     * may change dynamically during computation, the returned value
     * is only an approximation, but one that does not ever decrease
     * across successive calls.
     *
     * @return the number of tasks
     */
    public long getCompletedTaskCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            long n = completedTaskCount;
            for (Worker w : workers)
                n += w.completedTasks;
            return n;
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Returns a string identifying this pool, as well as its state,
     * including indications of run state and estimated worker and
     * task counts.
     *
     * @return a string identifying this pool, as well as its state
     */
    public String toString() {
        long ncompleted;
        int nworkers, nactive;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            ncompleted = completedTaskCount;
            nactive = 0;
            nworkers = workers.size();
            for (Worker w : workers) {
                ncompleted += w.completedTasks;
                if (w.isLocked())
                    ++nactive;
            }
        } finally {
            mainLock.unlock();
        }
        int c = ctl.get();
        String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" :
                     (runStateAtLeast(c, TERMINATED) ? "Terminated" :
                      "Shutting down"));
        return super.toString() +
            "[" + rs +
            ", pool size = " + nworkers +
            ", active threads = " + nactive +
            ", queued tasks = " + workQueue.size() +
            ", completed tasks = " + ncompleted +
            "]";
    }

    /* Extension hooks */

    /**
     * Method invoked prior to executing the given Runnable in the
     * given thread.  This method is invoked by thread {@code t} that
     * will execute task {@code r}, and may be used to re-initialize
     * ThreadLocals, or to perform logging.
     *
     * <p>This implementation does nothing, but may be customized in
     * subclasses. Note: To properly nest multiple overridings, subclasses
     * should generally invoke {@code super.beforeExecute} at the end of
     * this method.
     *
     * 在给定线程中执行给定Runnable之前调用的方法。
     * 该方法由执行任务{@code r}​​的线程{@code t}调用,可用于重新初始化ThreadLocals或执行日志记录。
     * 该实现不执行任何操作,但可以在子类中对其进行自定义。注意:要正确嵌套多个重写,子类通常应在此方法的末尾调用{@code super.beforeExecute}。
     *
     * @param t the thread that will run task {@code r}
     * @param r the task that will be executed
     */
    protected void beforeExecute(Thread t, Runnable r) { }

    /**
     * Method invoked upon completion of execution of the given Runnable.
     * This method is invoked by the thread that executed the task. If
     * non-null, the Throwable is the uncaught {@code RuntimeException}
     * or {@code Error} that caused execution to terminate abruptly.
     *
     * <p>This implementation does nothing, but may be customized in
     * subclasses. Note: To properly nest multiple overridings, subclasses
     * should generally invoke {@code super.afterExecute} at the
     * beginning of this method.
     * 给定Runnable执行完成时调用的方法。
     * 该方法由执行任务的线程调用。
     * 如果不为空,则Throwable是导致执行突然终止的未捕获{@code RuntimeException}或{@code Error}。
     * 该实现不执行任何操作,但可以在子类中对其进行自定义。
     * 注意:要正确嵌套多个重写,子类通常应在此方法的开头调用{@code super.afterExecute}。
     *
     * <p><b>Note:</b> When actions are enclosed in tasks (such as
     * {@link FutureTask}) either explicitly or via methods such as
     * {@code submit}, these task objects catch and maintain
     * computational exceptions, and so they do not cause abrupt
     * termination, and the internal exceptions are <em>not</em>
     * passed to this method. If you would like to trap both kinds of
     * failures in this method, you can further probe for such cases,
     * as in this sample subclass that prints either the direct cause
     * or the underlying exception if a task has been aborted:
     * 注意:如果将动作明确地或通过诸如{@code Submit}之类的方法包含在任务(例如{@link FutureTask})中,
     * 则这些任务对象会捕获并维护计算异常,因此它们不会导致突然终止,并且内部异常不会传递给此方法。
     * 如果您想使用此方法捕获两种类型的失败,则可以进一步探查此类情况.
     *
     *  <pre> {@code
     * class ExtendedExecutor extends ThreadPoolExecutor {
     *   // ...
     *   protected void afterExecute(Runnable r, Throwable t) {
     *     super.afterExecute(r, t);
     *     if (t == null && r instanceof Future<?>) {
     *       try {
     *         Object result = ((Future<?>) r).get();
     *       } catch (CancellationException ce) {
     *           t = ce;
     *       } catch (ExecutionException ee) {
     *           t = ee.getCause();
     *       } catch (InterruptedException ie) {
     *           Thread.currentThread().interrupt(); // ignore/reset
     *       }
     *     }
     *     if (t != null)
     *       System.out.println(t);
     *   }
     * }}</pre>
     *
     * @param r the runnable that has completed
     * @param t the exception that caused termination, or null if
     * execution completed normally
     */
    protected void afterExecute(Runnable r, Throwable t) { }

    /**
     * Method invoked when the Executor has terminated.  Default
     * implementation does nothing. Note: To properly nest multiple
     * overridings, subclasses should generally invoke
     * {@code super.terminated} within this method.
     *
     * 执行程序终止时调用的方法。
     * 默认实现不执行任何操作。
     * 注意:要正确嵌套多个重写,子类通常应在此方法内调用{@code super.terminated}。
     *
     */
    protected void terminated() { }

    /* Predefined RejectedExecutionHandlers */

    /**
     * 拒绝任务的处理程序,可以直接在{@code execute}方法的调用线程中运行拒绝任务,
     * 除非执行器已关闭,在这种情况下,该任务将被丢弃。
     */
    public static class CallerRunsPolicy implements RejectedExecutionHandler {
        public CallerRunsPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

    /**
     * 抛出{@code RejectedExecutionException}的拒绝任务处理程序。
     */
    public static class AbortPolicy implements RejectedExecutionHandler {
        public AbortPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

    public static class DiscardPolicy implements RejectedExecutionHandler {
        public DiscardPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }

    /**
     * 拒绝任务的处理程序,它丢弃最旧的未处理请求,然后重试{@code execute},
     * 除非执行器被关闭,在这种情况下,该任务将被丢弃。 
     */
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        public DiscardOldestPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }
}