1. 阅读Java线程池ThreadPoolExecutor源码
1.1前言
线程池主要解决两个问题:一方面当执行大量异步任务时候线程池能够提供较好的性能,这是因为使用线程池可以使每个任务的调用开销减少(因为线程池线程是可以复用的)。另一方面线程池提供了一种资源限制和管理的手段,比如当执行一系列任务时候对线程的管理,每个ThreadPoolExecutor也保留了一些基本的统计数据,比如当前线程池完成的任务数目。
另外,线程池提供许多可调参数和可扩展性钩子。程序员可以使用更方便。工厂方法比如newCachedThreadPool(无限线程池,线程自动回收),newFixedThreadPool(固定大小的线程池)newSingleThreadExecutor(单个线程),当然用户还可以自定义。
先来一张整体流程图,看一下ThreadPoolExecutor的处理逻辑:
1.2线程池的若干状态
/** * The main pool control state, ctl, is an atomic integer packing * two conceptual fields * workerCount, indicating the effective number of threads * runState, indicating whether running, shutting down etc * 线程池主要的控制状态值ctl是一个院子类型的整数值,它封装了两个概念上的域: * workerCount:标识了当先有效的线程数 * runState:标识运行、关闭等状态 * * In order to pack them into one int, we limit workerCount to * (2^29)-1 (about 500 million) threads rather than (2^31)-1 (2 * billion) otherwise representable. If this is ever an issue in * the future, the variable can be changed to be an AtomicLong, * and the shift/mask constants below adjusted. But until the need * arises, this code is a bit faster and simpler using an int. * * 为了将这两个变量封装到一个整型数值中,我们限制了 workerCount的上限在(2^29)-1(大约 * 5亿左右)而不是(2^31)-1(20亿左右)。如果整型值在未来是个问题,整型值可以替换成 * 原子类型长整型,位移/掩码变量可以随之调整。但是除非是需求上涨,否则用int会更快更简单些。 * * The workerCount is the number of workers that have been * permitted to start and not permitted to stop. The value may be * transiently different from the actual number of live threads, * for example when a ThreadFactory fails to create a thread when * asked, and when exiting threads are still performing * bookkeeping before terminating. The user-visible pool size is * reported as the current size of the workers set. * * workerCount是允许运行并且不允许停止的工作线程数。该值可能与实际活跃线程的数量不同。 * 比如线程工厂创建线程失败且线程在终止之前人执行簿记工作。用户可见的线程池大小是当前工作线程集合打大小 * * The runState provides the main lifecyle control, taking on values: * 运行状态提供了主要的生命周期控制,接受一下值: * * RUNNING: Accept new tasks and process queued tasks * SHUTDOWN: Don't accept new tasks, but process queued tasks * STOP: Don't accept new tasks, don't process queued tasks, * and interrupt in-progress tasks * TIDYING: All tasks have terminated, workerCount is zero, * the thread transitioning to state TIDYING * will run the terminated() hook method * TERMINATED: terminated() has completed * * RUNNING:接受新任务并处理队列中的任务 * SHUTDOWN:不接受新任务,但是处理队列中的任务 * STOP:不接受新的任务,也不会处理队列中的任务,并且会中断处理中的任务 * TIDYING:所有的任务终止,workerCount=0,线程过度到TIDYING状态将会执行terminated() * 钩子函数。 * * * The numerical order among these values matters, to allow * ordered comparisons. The runState monotonically increases over * time, but need not hit each state. The transitions are: * * 这些值之间的数值顺序很重要,可以进行排序比较。运行状态单调地随时间增加,但不需要对经历所有状态。 * * RUNNING -> SHUTDOWN * On invocation of shutdown(), perhaps implicitly in finalize() * 调用shutdown方法或者隐式的调用finalize方法 * * (RUNNING or SHUTDOWN) -> STOP * On invocation of shutdownNow() * 调用shutdownNow方法的时候 * * SHUTDOWN -> TIDYING * When both queue and pool are empty * 队列和线程池都为空的时候 * * STOP -> TIDYING * When pool is empty * 线程池为空 * * TIDYING -> TERMINATED * When the terminated() hook method has completed * terminated()钩子函数执行完成 * * Threads waiting in awaitTermination() will return when the * state reaches TERMINATED. * * Detecting the transition from SHUTDOWN to TIDYING is less * straightforward than you'd like because the queue may become * empty after non-empty and vice versa during SHUTDOWN state, but * we can only terminate if, after seeing that it is empty, we see * that workerCount is 0 (which sometimes entails a recheck -- see * below). * 探测状态从SHUTDOWN到TIDYING可能并不想你想象的直接,因为队列可能在非空状态后又变成空队列, * 反之亦然。只有在看到它是空的之后,我们才可以终止,我们看到,workerCount是0 */ //一个变量存储线程池状态 和 线程池线程个数两个信息。 //初始状态:ctl = 111100000,00000000,00000000,00000000 //用来标记线程池状态(高3位),线程个数(低29位)默认是RUNNING状态,线程个数为0 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); //COUNT_BITS = 29,线程个数掩码位数 private static final int COUNT_BITS = Integer.SIZE - 3; //线程最大个数,CAPACITY = 00011111,11111111,11111111,11111111 private static final int CAPACITY = (1 << COUNT_BITS) - 1; // runState is stored in the high-order bits //运行状态保存在高位 //高3位是111,RUNNING = 111100000,00000000,00000000,00000000 //接受新任务并且处理阻塞队列里的任务 private static final int RUNNING = -1 << COUNT_BITS; //高3位是000,SHUTDOWN = 00000000,00000000,00000000,00000000 //拒绝新任务但是处理阻塞队列里的任务 private static final int SHUTDOWN = 0 << COUNT_BITS; //高3位是001,STOP = 00100000,00000000,00000000,00000000 //拒绝新任务并且抛弃阻塞队列里的任务同时会中断正在处理的任务 private static final int STOP = 1 << COUNT_BITS; //高3位是010,TIDYING = 01000000,00000000,00000000,00000000 //所有任务都执行完(包含阻塞队列里任务)当前线程池活动线程为0,将要调用terminated方法 private static final int TIDYING = 2 << COUNT_BITS; //高3位是011,TERMINATED = 01100000,00000000,00000000,00000000 //终止状态。terminated方法调用完成以后的状态 private static final int TERMINATED = 3 << COUNT_BITS;
1.3有关运行状态的操作
/** * 获取高三位当前线程池的状态 * c和~CAPACITY做与运算 * ~CAPACITY = 11100000,00000000,00000000,00000000 * c和~CAPACITY做与操作,导致c的最高3位保留,c的低29位为0 * 也就是上面定义的几种状态RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED * @param c * @return */ private static int runStateOf(int c) { return c & ~CAPACITY; } // c与CAPACITY做与运算,得到c的低29位二进制,也就是工作线程数 private static int workerCountOf(int c) { return c & CAPACITY; } //rs和wc做或运算,计算ctl新值 private static int ctlOf(int rs, int wc) { return rs | wc; } /* * Bit field accessors that don't require unpacking ctl. * These depend on the bit layout and on workerCount being never negative. * * 不需要拆包的位字段访问器。这依赖于位的布局和workerCount永远不会是一个负数。 */ //运行状态小于s private static boolean runStateLessThan(int c, int s) { return c < s; } //运行状态不小于s private static boolean runStateAtLeast(int c, int s) { return c >= s; } //当前线程数是否小于0,小于0表示运行状态 private static boolean isRunning(int c) { return c < SHUTDOWN; } /** * Attempt to CAS-increment the workerCount field of ctl. * 尝试使用CAS的增加ctl中维护的workerCount域的值 */ private boolean compareAndIncrementWorkerCount(int expect) { return ctl.compareAndSet(expect, expect + 1); } /** * Attempt to CAS-decrement the workerCount field of ctl. * 尝试使用CAS的减少ctl中维护的workerCount域的值 */ private boolean compareAndDecrementWorkerCount(int expect) { return ctl.compareAndSet(expect, expect - 1); } /** * Decrements the workerCount field of ctl. This is called only on * abrupt termination of a thread (see processWorkerExit). Other * decrements are performed within getTask. * * 减少ctl的工作线程数。此方法只有在线程突然中止的时候调用(详情参见processWorkerExit) * 其他情况减少线程数在getTask中执行 */ private void decrementWorkerCount() { do {} while (! compareAndDecrementWorkerCount(ctl.get())); }
1.4阻塞队列
/** * The queue used for holding tasks and handing off to worker * threads. We do not require that workQueue.poll() returning * null necessarily means that workQueue.isEmpty(), so rely * solely on isEmpty to see if the queue is empty (which we must * do for example when deciding whether to transition from * SHUTDOWN to TIDYING). This accommodates special-purpose * queues such as DelayQueues for which poll() is allowed to * return null even if it may later return non-null when delays * expire. * * 用于保存任务并将其传递给工作线程的队列。不用workQueue.poll()返回null来判断队列 * 为空,仅仅根据isEmpty就 可以知道队列是否为空。(这是决定是否要将状态从SHUTDOWN * 转变到TIDYING必须要检查的)。此队列满足特殊目的的队列,如即使在稍后会返回非空值,但是 * 本次在延迟超时之后,可以从poll方法返回null的DelayQueues。 */ private final BlockingQueue<Runnable> workQueue;
1.5重入锁
/** * Lock held on access to workers set and related bookkeeping. * While we could use a concurrent set of some sort, it turns out * to be generally preferable to use a lock. Among the reasons is * that this serializes interruptIdleWorkers, which avoids * unnecessary interrupt storms, especially during shutdown. * Otherwise exiting threads would concurrently interrupt those * that have not yet interrupted. It also simplifies some of the * associated statistics bookkeeping of largestPoolSize etc. We * also hold mainLock on shutdown and shutdownNow, for the sake of * ensuring workers set is stable while separately checking * permission to interrupt and actually interrupting. * * 访问工作线程集合和相关簿记工作持有的锁。虽然我为了们可以使用某种类型的并发集,但通常情况下, * 使用锁是比较可取的。其中的一个原因就是,这些连续的interruptIdleWorkers,尤其 * 是在关闭关闭期间,避免了不必要的中断。然而线程退出将并发中断尚未中断的线程。它也简化了 * largestPoolSize的相关的统计操作。在检查中断,和实际中断操作权限时,为了确保工作线程集是稳定, * 我们在执行shutdown和shutdownNow时也持有mainLock锁。 */ private final ReentrantLock mainLock = new ReentrantLock();
1.6线程集合
/** * Set containing all worker threads in pool. Accessed only when * holding mainLock. * 池中维护所有工作线程的Set集合。只能在持有mainLock锁的时候才能访问。 */ private final HashSet<java.util.concurrent.ThreadPoolExecutor.Worker> workers = new HashSet<java.util.concurrent.ThreadPoolExecutor.Worker>();
1.7线程池参数
/** * Wait condition to support awaitTermination * 等待条件以支持awaitTermination */ private final Condition termination = mainLock.newCondition(); /** * Tracks largest attained pool size. Accessed only under * mainLock. * * 记录达到的最大的线程数,只能在mainLock锁保护下访问 */ private int largestPoolSize; /** * Counter for completed tasks. Updated only on termination of * worker threads. Accessed only under mainLock. * * 完成的任务计数器。只有在工作线程终止的时候更新。必须在mainLock保护下访问 */ private long completedTaskCount; /* * All user control parameters are declared as volatiles so that * ongoing actions are based on freshest values, but without need * for locking, since no internal invariants depend on them * changing synchronously with respect to other actions. * * 所有用户控制的参数都被声明为volatile,这样正在进行中的操作都是基于最新的值的,但是没有必要 * 加锁,因为没有内部的变量依赖于它们在其他操作上的同步变化。 */ /** * Factory for new threads. All threads are created using this * factory (via method addWorker). All callers must be prepared * for addWorker to fail, which may reflect a system or user's * policy limiting the number of threads. Even though it is not * treated as an error, failure to create threads may result in * new tasks being rejected or existing ones remaining stuck in * the queue. * * 创建新线程的工厂。所有都是用这个工厂创建的。(通过addWorker方法)所有调用者必须为addWorker * 失败做好准备,这可能反应了系统或用户限制线程数量的策略。尽管创建新线程失败不会被当成是错误, * 但是创建失败可能会导致新任务被拒绝或者现有线程被阻塞在队列中不能被执行。 * * We go further and preserve pool invariants even in the face of * errors such as OutOfMemoryError, that might be thrown while * trying to create threads. Such errors are rather common due to * the need to allocate a native stack in Thread#start, and users * will want to perform clean pool shutdown to clean up. There * will likely be enough memory available for the cleanup code to * complete without encountering yet another OutOfMemoryError. * * 即使在创建新线程时,面临像OutOfMemoryError的错误,我们也会进一步维护池不变量。由于 * 因为要为Thread的start分配native stack空间,这些错误是正常的,用户将执行清理线程池。 * 在不遇到另一个OutOfMemoryError错误的情况下,可能有足够的内存可用来完成清理代码。 * */ private volatile ThreadFactory threadFactory; /** * Handler called when saturated or shutdown in execute. * Handler在线程池饱和或者关闭的时候调用 */ private volatile RejectedExecutionHandler handler; /** * Timeout in nanoseconds for idle threads waiting for work. * Threads use this timeout when there are more than corePoolSize * present or if allowCoreThreadTimeOut. Otherwise they wait * forever for new work. * * 空闲线程等待任务超时时间,单位是纳秒。当现有的线程数超过corePoolSize或者 * allowCoreThreadTimeOut为true,线程将会使用这个超时时间。否则线程将 * 永远等待新任务的到来。 * */ private volatile long keepAliveTime; /** * If false (default), core threads stay alive even when idle. * If true, core threads use keepAliveTime to time out waiting * for work. * 如果为false(默认),在空闲的时候核心线程尽管也会保持活跃。如果为true,那么核心线程将 * 在keepAliveTime的超时时间内等待新任务。 */ private volatile boolean allowCoreThreadTimeOut; /** * Core pool size is the minimum number of workers to keep alive * (and not allow to time out etc) unless allowCoreThreadTimeOut * is set, in which case the minimum is zero. * * 不允许线程超时的情况,线程池核心线程个数是最小的活跃的工作线程数,否则,核心线程数最小值为0 * */ private volatile int corePoolSize; /** * Maximum pool size. Note that the actual maximum is internally * bounded by CAPACITY. * * 线程池最大线程数。注意,实际的最大值在内部是由容量限制的。 */ private volatile int maximumPoolSize; /** * The default rejected execution handler * * 默认的拒绝执行策略 */ private static final RejectedExecutionHandler defaultHandler = new java.util.concurrent.ThreadPoolExecutor.AbortPolicy(); /** * Permission required for callers of shutdown and shutdownNow. * We additionally require (see checkShutdownAccess) that callers * have permission to actually interrupt threads in the worker set * (as governed by Thread.interrupt, which relies on * ThreadGroup.checkAccess, which in turn relies on * SecurityManager.checkAccess). Shutdowns are attempted only if * these checks pass. * * 调用shutdown和shutdownNow需要的权限。我们也要求调用者有权限去中断线程集合中的线程。 * (Thread.interrupt依赖ThreadGroup.checkAccess,反过来又依赖于 * SecurityManager.checkAccess)关闭线程只能在权限校验通过才能执行。 * * All actual invocations of Thread.interrupt (see * interruptIdleWorkers and interruptWorkers) ignore * SecurityExceptions, meaning that the attempted interrupts * silently fail. In the case of shutdown, they should not fail * unless the SecurityManager has inconsistent policies, sometimes * allowing access to a thread and sometimes not. In such cases, * failure to actually interrupt threads may disable or delay full * termination. Other uses of interruptIdleWorkers are advisory, * and failure to actually interrupt will merely delay response to * configuration changes so is not handled exceptionally. * * 所有对Thread.interrupt方法的调用都忽略了安全异常。这就意味着尝试中断会无声的中断。 * 在关闭的情况下,除非SecurityManager具有不一致的策略,否则它们不应该失败, * 有时允许访问线程,有时不允许访问。这种情况下,如果不能真正中断线程,可能会紧张或延迟 * 完全终止。中断服务的其他用途是咨询性的,而实际上的中断只会延迟对配置更改的响应,所以不处理异常 */ private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread"); /** * Permission required for callers of shutdown and shutdownNow. * We additionally require (see checkShutdownAccess) that callers * have permission to actually interrupt threads in the worker set * (as governed by Thread.interrupt, which relies on * ThreadGroup.checkAccess, which in turn relies on * SecurityManager.checkAccess). Shutdowns are attempted only if * these checks pass. * * 调用shutdown和shutdownNow需要的权限。我们也要求调用者有权限去中断线程集合中的线程。 * (Thread.interrupt依赖ThreadGroup.checkAccess,反过来又依赖于 * SecurityManager.checkAccess)关闭线程只能在权限校验通过才能执行。 * * All actual invocations of Thread.interrupt (see * interruptIdleWorkers and interruptWorkers) ignore * SecurityExceptions, meaning that the attempted interrupts * silently fail. In the case of shutdown, they should not fail * unless the SecurityManager has inconsistent policies, sometimes * allowing access to a thread and sometimes not. In such cases, * failure to actually interrupt threads may disable or delay full * termination. Other uses of interruptIdleWorkers are advisory, * and failure to actually interrupt will merely delay response to * configuration changes so is not handled exceptionally. * * 所有对Thread.interrupt方法的调用都忽略了安全异常。这就意味着尝试中断会无声的失败。 * 在关闭的情况下,除非SecurityManager具有不一致的策略,否则它们不应该失败, * 有时允许访问线程,有时不允许访问。这种情况下,如果不能真正中断线程,可能会阻止或延迟 * 完全终止。interruptIdleWorkers的其他用途是咨询性的,而实际上的中断只会延迟对配置更改的响应, * 所以不处理异常 */ private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread");
1.8构造函数
/** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters and default thread factory and rejected execution handler. * It may be more convenient to use one of the {@link Executors} factory * methods instead of this general purpose constructor. * 用给定参数和默认的线程工厂和拒绝策略创建一个新线程池。用Executors类的工厂方法可以比此构造器更加方便实现创建线程池。 * * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param maximumPoolSize the maximum number of threads to allow in the * pool * @param keepAliveTime when the number of threads is greater than * the core, this is the maximum time that excess idle threads * will wait for new tasks before terminating. * @param unit the time unit for the {@code keepAliveTime} argument * @param workQueue the queue to use for holding tasks before they are * executed. This queue will hold only the {@code Runnable} * tasks submitted by the {@code execute} method. * @throws IllegalArgumentException if one of the following holds:<br> * {@code corePoolSize < 0}<br> * {@code keepAliveTime < 0}<br> * {@code maximumPoolSize <= 0}<br> * {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} is null */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); } /** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters and default rejected execution handler. * 用给定参数和默认的线程和默认的拒绝策略创建一个新线程池。 * * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param maximumPoolSize the maximum number of threads to allow in the * pool * @param keepAliveTime when the number of threads is greater than * the core, this is the maximum time that excess idle threads * will wait for new tasks before terminating. * @param unit the time unit for the {@code keepAliveTime} argument * @param workQueue the queue to use for holding tasks before they are * executed. This queue will hold only the {@code Runnable} * tasks submitted by the {@code execute} method. * @param threadFactory the factory to use when the executor * creates a new thread * @throws IllegalArgumentException if one of the following holds:<br> * {@code corePoolSize < 0}<br> * {@code keepAliveTime < 0}<br> * {@code maximumPoolSize <= 0}<br> * {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} * or {@code threadFactory} is null */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler); } /** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters and default thread factory. * 用给定的参数和默认的线程工厂创建一个新线程池。 * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param maximumPoolSize the maximum number of threads to allow in the * pool * @param keepAliveTime when the number of threads is greater than * the core, this is the maximum time that excess idle threads * will wait for new tasks before terminating. * @param unit the time unit for the {@code keepAliveTime} argument * @param workQueue the queue to use for holding tasks before they are * executed. This queue will hold only the {@code Runnable} * tasks submitted by the {@code execute} method. * @param handler the handler to use when execution is blocked * because the thread bounds and queue capacities are reached * @throws IllegalArgumentException if one of the following holds:<br> * {@code corePoolSize < 0}<br> * {@code keepAliveTime < 0}<br> * {@code maximumPoolSize <= 0}<br> * {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} * or {@code handler} is null */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler); } /** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters. * 用给定参数创建一个线程池 * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param maximumPoolSize the maximum number of threads to allow in the * pool * @param keepAliveTime when the number of threads is greater than * the core, this is the maximum time that excess idle threads * will wait for new tasks before terminating. * @param unit the time unit for the {@code keepAliveTime} argument * @param workQueue the queue to use for holding tasks before they are * executed. This queue will hold only the {@code Runnable} * tasks submitted by the {@code execute} method. * @param threadFactory the factory to use when the executor * creates a new thread * @param handler the handler to use when execution is blocked * because the thread bounds and queue capacities are reached * @throws IllegalArgumentException if one of the following holds:<br> * {@code corePoolSize < 0}<br> * {@code keepAliveTime < 0}<br> * {@code maximumPoolSize <= 0}<br> * {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} * or {@code threadFactory} or {@code handler} is null */ 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.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
下面来看看Executors中的线程工厂:
newFixedThreadPool
创建一个核心线程个数和最大线程个数都为nThreads的线程池,并且阻塞队列长度为Integer.MAX_VALUE,keeyAliveTime=0说明只要线程个数比核心线程个数多并且当前空闲则回收。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory); }
newSingleThreadExecutor
创建一个核心线程个数和最大线程个数都为1的线程池,并且阻塞队列长度为Integer.MAX_VALUE,keeyAliveTime=0说明只要线程个数比核心线程个数多并且当前空闲则回收。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory)); }
newCachedThreadPool
创建一个按需创建线程的线程池,初始线程个数为0,最多线程个数为Integer.MAX_VALUE,并且阻塞队列为同步队列,keeyAliveTime=60说明只要当前线程60s内空闲则回收。这个特殊在于加入到同步队列的任务会被马上被执行,同步队列里面最多只有一个任务,并且存在后马上会拿出执行。
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); } public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
newSingleThreadScheduledExecutor
创建一个最小线程个数corePoolSize为1,最大为Integer.MAX_VALUE,阻塞队列为DelayedWorkQueue的线程池。
public static ScheduledExecutorService newSingleThreadScheduledExecutor() { return new DelegatedScheduledExecutorService (new ScheduledThreadPoolExecutor(1)); } public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) { return new DelegatedScheduledExecutorService (new ScheduledThreadPoolExecutor(1, threadFactory)); }
newScheduledThreadPool
创建一个最小线程个数corePoolSize,最大为Integer.MAX_VALUE,阻塞队列为DelayedWorkQueue的线程池。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } public static ScheduledExecutorService newSingleThreadScheduledExecutor() { return new DelegatedScheduledExecutorService (new ScheduledThreadPoolExecutor(1)); }
1.9添加任务到线程池exectue方法
/** * 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}. * 如果因为执行器被关闭或者执行器打到了最大容量而导致任务不能被 * 提交执行,该任务将由当前的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(); /* * 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. * 1.如果线程数小于正在运行的corePoolSize线程数,首要任务 * 是尝试使用给定命令开启新的线程。对addWorker方法的调用 * 会原子性地检查runState和workerCount以防止不应该添加 * 线程错误报警时返回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. * 2. 如果一个任务可以成功的进入队列,那么我们仍然需要再次检查 * 是否应该添加一个线程(由于已有的线程自上次检查后消亡了)或 * 进入方法后线程池关闭了。所以我们需要重新检查状态,如果停止 * 的话,回滚入队操作。如果没有线程可用,创建新线程 * * 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. * 3.如果不能把任务加入队列,我们就尝试创建新的线程。如果失败, * 我们就知道线程池关闭了或者已经饱和了,所以我们就拒绝任务。 */ //取得当前ctl的数值 int c = ctl.get(); /** * workerCountOf获取ctl的低29位,也就是当前池中的线程数 * 如果当前线程数 < corePoolSize(核心线程数) */ if (workerCountOf(c) < corePoolSize) { //创建新线程执行任务 if (addWorker(command, true)) return; c = ctl.get(); } /** * 池中的线程数 = corePoolSize会走下面的逻辑(不会有大于的情况发生) * 线程池未停止 && 加入队列成功,执行以下 */ if (isRunning(c) && workQueue.offer(command)) { //再次检查当前线程数 int recheck = ctl.get(); //线程池已经停止 && 删除workQueue.offer(command)中的任务成功 if (! isRunning(recheck) && remove(command)) //拒绝任务 reject(command); //如果线程池未停止 或者 线程池已经停止,队列删除任务失败,如果线程数=0 else if (workerCountOf(recheck) == 0) //创建新线程来执行任务 addWorker(null, false); } //创建新的线程失败,拒绝该任务 else if (!addWorker(command, false)) reject(command); }
1.10addWorker方法
/** * Checks if a new worker can be added with respect to current * pool state and the given bound (either core or maximum). If so, * the worker count is adjusted accordingly, and, if possible, a * new worker is created and started, running firstTask as its * first task. This method returns false if the pool is stopped or * eligible to shut down. It also returns false if the thread * factory fails to create a thread when asked. If the thread * creation fails, either due to the thread factory returning * null, or due to an exception (typically OutOfMemoryError in * Thread#start), we roll back cleanly. * * 检查是否可以根据当前的池状态和给定的界限(核心或最大值)添加新的工作者线程 * 如果可以,工作者线程会相应的做出调整,如果可能的话,一个新的工作者线程被创建 * 和运行,将firstTask作为的一个任务。如果线程池停止或者合法关闭,此方法 * 返回false。如果线程工厂在被访问时,没能成功创建线程,此方法也会返回false。 * 如果因为线程工厂返回null或者是因为异常(典型的在Thread中的start方法抛出的 * OutOfMemoryError异常)线程创建失败,我们都会干净的回滚。 * * * @param firstTask the task the new thread should run first (or * null if none). Workers are created with an initial first task * (in method execute()) to bypass queuing when there are fewer * than corePoolSize threads (in which case we always start one), * or when the queue is full (in which case we must bypass queue). * Initially idle threads are usually created via * prestartCoreThread or to replace other dying workers. * firstTask是新的线程必须首先执行的(如果没有的话就为null)。工作线程在创建的时候就初始化了 * 首先要执行的任务(在execute方法中的任务),以便当线程数小于corePoolSize时(这种情况下 * 必须创建新的线程)或者是队列已满时(这种情况下我们必须绕过队列)我们必须绕过队列。最初的空闲线程 * 通常是通过prestartCoreThread或者替换其他消亡的工作线程时创建的。 * * @param core if true use corePoolSize as bound, else * maximumPoolSize. (A boolean indicator is used here rather than a * value to ensure reads of fresh values after checking other pool * state). * 如果core为true,使用corePoolSize作为绑定,否则使用maximumPoolSize做绑定。(一个布尔 * 类型的指示器用在这里,而不是在检查其他池状态后确保读取新值的值) * * @return true if successful */ 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() * 至少有一个为false的时候,返回false * (不明白这是干嘛的) */ if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) { //当前线程数 int wc = workerCountOf(c); /** * 当前线程数 > 最大线程数 或者 * 当前创建核心线程 && 当前线程数 > corePoolSize或者 * 当前创建非核心线程 && 当前线程数 > maximumPoolSize * 返回失败 */ if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; //CAS操作设置ctl自增1 if (compareAndIncrementWorkerCount(c)) //跳出当前循环,也就是最外层for循环 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 java.util.concurrent.ThreadPoolExecutor.Worker w = null; try { final ReentrantLock mainLock = this.mainLock; //创建工作线程 w = new java.util.concurrent.ThreadPoolExecutor.Worker(firstTask); final Thread t = w.thread; if (t != null) { //加锁 mainLock.lock(); try { // Recheck while holding lock. // Back out on ThreadFactory failure or if // shut down before lock acquired. //持有锁的时候重现检查。 //退出ThreadFactory失败,或者在获取锁之前关闭。 int c = ctl.get(); int rs = runStateOf(c); //rs < SHUTDOWN只有RUNNING状态 //当为RUNNING状态或者SHUTDOWN状态,且firstTask == null if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); //新线程加入workers这个HashSet中 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; }
1.11工作线程
/** * Class Worker mainly maintains interrupt control state for * threads running tasks, along with other minor bookkeeping. * This class opportunistically extends AbstractQueuedSynchronizer * to simplify acquiring and releasing a lock surrounding each * task execution. This protects against interrupts that are * intended to wake up a worker thread waiting for a task from * instead interrupting a task being run. We implement a simple * non-reentrant mutual exclusion lock rather than use * ReentrantLock because we do not want worker tasks to be able to * reacquire the lock when they invoke pool control methods like * setCorePoolSize. Additionally, to suppress interrupts until * the thread actually starts running tasks, we initialize lock * state to a negative value, and clear it upon start (in * runWorker). * * Worker类主要维护执行任务的线程的中断控制状态,以及其他一些小范围的簿记。 * 这个类机会性的继承了AbstractQueuedSynchronizer以便简化围绕每个任务执行 * 时的锁的获取与释放。这可以防止中断打算唤醒等待任务的工作线程,从而避免 * 中断正在运行的任务。我们实现了一个简单的非重入互斥锁,而不是使用ReentrantLock, * 因为我们不希望工作任务在调用像setCorePoolSize这样的池控制方法时能够重新获取锁。 * 另外,为了在线程实际开始运行任务之前禁止中断,我们初始化锁的状态为一个负值,并在 * 启动线程开始执行任务时清除这个负值(在runWorker方法中) * */ private final class Worker extends AbstractQueuedSynchronizer implements Runnable { /** * This class will never be serialized, but we provide a * serialVersionUID to suppress a javac warning. * 这个类永远不会被序列化,但是我们提供serialVersionUID来抑制java编译告警 */ private static final long serialVersionUID = 6138294804551838833L; /** Thread this worker is running in. Null if factory fails. */ /** worker对象运行的线程,如果线程工厂运行失败,可能为空 */ final Thread thread; /** Initial task to run. Possibly null. */ /** 最初要执行的任务,可能为空 */ Runnable firstTask; /** Per-thread task counter */ /** 每个线程的任务计数器 */ volatile long completedTasks; /** * Creates with given first task and thread from ThreadFactory. * 用firstTask和从线程工厂创建的线程对象创建Worker对象 * @param firstTask the first task (null if none) */ Worker(Runnable firstTask) { //调用runWorker方法之前禁止中断 /** * 这里添加一个新状态-1是为了避免当前worker线程被中断, * 比如调用了线程池的shutdownNow,如果当前worker状态>=0则会设置该线程的中断标志。 * 这里设置了-1所以条件不满足就不会中断该线程了。运行runWorker时候会调用unlock方法, * 该方法吧status变为了0,所以这时候调用shutdownNow会中断worker线程。 */ setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); } /** Delegates main run loop to outer runWorker */ /** 委托外部类的runWorker执行任务 */ public void run() { runWorker(this); } // Lock methods // // The value 0 represents the unlocked state. // The value 1 represents the locked state. //加锁方法,0表示未加锁,1表示加锁 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) { } } } }
1.12 runWorker
/** * Main worker run loop. Repeatedly gets tasks from queue and * executes them, while coping with a number of issues: * * 1. We may start out with an initial task, in which case we * don't need to get the first one. Otherwise, as long as pool is * running, we get tasks from getTask. If it returns null then the * worker exits due to changed pool state or configuration * parameters. Other exits result from exception throws in * external code, in which case completedAbruptly holds, which * usually leads processWorkerExit to replace this thread. * * 2. Before running any task, the lock is acquired to prevent * other pool interrupts while the task is executing, and * clearInterruptsForTaskRun called to ensure that unless pool is * stopping, this thread does not have its interrupt set. * * 3. Each task run is preceded by a call to beforeExecute, which * might throw an exception, in which case we cause thread to die * (breaking loop with completedAbruptly true) without processing * the task. * * 4. Assuming beforeExecute completes normally, we run the task, * gathering any of its thrown exceptions to send to * afterExecute. We separately handle RuntimeException, Error * (both of which the specs guarantee that we trap) and arbitrary * Throwables. Because we cannot rethrow Throwables within * Runnable.run, we wrap them within Errors on the way out (to the * thread's UncaughtExceptionHandler). Any thrown exception also * conservatively causes thread to die. * * 5. After task.run completes, we call afterExecute, which may * also throw an exception, which will also cause thread to * die. According to JLS Sec 14.20, this exception is the one that * will be in effect even if task.run throws. * * The net effect of the exception mechanics is that afterExecute * and the thread's UncaughtExceptionHandler have as accurate * information as we can provide about any problems encountered by * user code. * * @param w the worker */ final void runWorker(java.util.concurrent.ThreadPoolExecutor.Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { //如果当前task非空,则直接执行。否者调用getTask从任务队列获取一个任务执行, // 如果任务队列为空,则worker退出。 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 // 如果线程池是最少是stop状态(STOP,TIDYING,TERMINATED),则设置中断标志; // 否则(RUNNININ状态),重置中断标志。重置后需要重新 //检查一下线程池状态,因为当重置中断标志时候,可能调用了线程池的shutdown方法 //改变了线程池状态。 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; //统计当前worker完成了多少个任务 w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { //执行清理工作 processWorkerExit(w, completedAbruptly); } }
1.13 beforeExecute、afterExecute和processWorkerExit
/* 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. * * 在给定线程执行给定Runnable任务之前执行的方法。此方法由将要执行任务r的线程t * 调用,并且可能会用来重新初始化ThreadLocals或者打印一些日志。 * * <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. * 这个方法的实现什么都不做,但是可以在子类中定制化。注意:为了正确的实现多层 * 重写,子类通常该方法结束时调用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. * * 此方法在执行完Runnable任务后调用。此方法是被执行任务的线程调用的。如果非空 * 那么Throwable就是导致执行突然中断的未捕获的运行时异常或者错误。 * * <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. * 这个方法的实现什么都不做,但是可以在子类中定制化。注意:为了正确的实现多层 * 重写,子类通常该方法结束时调用super.beforeExecute。 * * <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: * * 当操作被明确的封装在如FutureTask这样的任务中,或者通过submit方法提交任务时, * 这些对象会捕获并处理计算异常,所以这些对象不会导致不会导致突然执行中断,并且 * 内部异常不会传递此方法。如果你想在此方法中捕获以上两种异常,则可以进一步探测此类情况 * 例如在一个简单的子类中,如果任务被终止,则打印这的异常原因或者底层异常。 * * <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) { } /** * Performs cleanup and bookkeeping for a dying worker. Called * only from worker threads. Unless completedAbruptly is set, * assumes that workerCount has already been adjusted to account * for exit. This method removes thread from worker set, and * possibly terminates the pool or replaces the worker if either * it exited due to user task exception or if fewer than * corePoolSize workers are running or queue is non-empty but * there are no workers. * * 为消亡的线程执行清理和簿记工作。仅从工作线程调用。除非completedAbruptly * 被设定了,否则假定workerCount已经考虑到退出而做了调整到。此方法从工作线程集合 * 中删除线程,并且可能因为用户任务异常或者线程数小于corePoolSize * 工作线程数或者阻塞队列非空,但是没有工作线程而可能会终止该池或替换该工作。 * @param w the worker * @param completedAbruptly if the worker died due to user exception */ private void processWorkerExit(java.util.concurrent.ThreadPoolExecutor.Worker w, boolean completedAbruptly) { if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //统计整个线程池完成的任务个数 completedTaskCount += w.completedTasks; //删除工作线程 workers.remove(w); } finally { mainLock.unlock(); } //尝试设置线程池状态为TERMINATED,如果当前是shutdonw状态并且工作队列为空 //或者当前是stop状态当前线程池里面没有活动线程 tryTerminate(); int c = ctl.get(); //SHUTDOWN或RUNNING if (runStateLessThan(c, STOP)) { if (!completedAbruptly) { int min = allowCoreThreadTimeOut ? 0 : corePoolSize; if (min == 0 && ! workQueue.isEmpty()) min = 1; if (workerCountOf(c) >= min) return; // replacement not needed } //如果当前线程个数小于核心个数,则增加 addWorker(null, false); } }
1.14 shutdown、shutdownNow
/** * 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. * * 此方法不会等待之前所有的任务都执行完,awaitTermination可以达到该效果。 * * @throws SecurityException {@inheritDoc} */ public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //权限检查 checkShutdownAccess(); //设置当前线程池状态为SHUTDOWN,如果已经是SHUTDOWN则直接返回 advanceRunState(SHUTDOWN); //设置中断标志 interruptIdleWorkers(); //为ScheduledThreadPoolExecutor预留的钩子函数 onShutdown(); // hook for ScheduledThreadPoolExecutor } finally { mainLock.unlock(); } //尝试状态变为TERMINATED 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. * * 尝试停止所有执行中的任务,停止等待任务的线程,返回一个要执行的任务的list。 * 从这个方法返回后,这些任务从队列中删除。 * * <p>This method does not wait for actively executing tasks to * terminate. Use {@link #awaitTermination awaitTermination} to * do that. * * 这个方法不会等待执行中的任务执行结束,用awaitTermination实现。 * * <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. * * 尽最大可能的停止处理中的任务,不能保证结果。这种实现方式通过interrupt取消 * 任务,所以任何任务没有能够响应interrupt可能永远都不能终止, * * @throws SecurityException {@inheritDoc} */ public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //权限检查 checkShutdownAccess(); //设置线程池状态为stop advanceRunState(STOP); //中断线程 interruptWorkers(); //移动队列任务到tasks tasks = drainQueue(); } finally { mainLock.unlock(); } //尝试状态变为TERMINATED tryTerminate(); return tasks; }