前言
相关系列
- 《Java & Executor & 目录》
- 《Java & Executor & ThreadPoolExecutor & 源码》
- 《Java & Executor & ThreadPoolExecutor & 总结》
- 《Java & Executor & ThreadPoolExecutor & 问题》
涉及内容
- 《Java & Executor & 总结》
- 《Java & Executor & ExecutorService & 总结》
- 《Java & Executor & Future & 总结》
- 《Java & Executor & FutureTask & 总结》
- 《Java & Collection/Executor & BlockingQueue & 总结》
- 《Java & Thread & Runnable & 总结》
源码
/*
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/*
*
*
*
*
*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
package juc;
import juc.locks.AbstractQueuedSynchronizer;
import juc.locks.Condition;
import juc.locks.ReentrantLock;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* An {@link ExecutorService} that executes each submitted task using one of possibly several pooled threads, normally configured
* using {@link Executors} factory methods.
* 一个执行器服务可能使用多个池线程的其中一个来执行每个递交任务(即有任务递交时,会从池线程中选择一个来执行),通常使
* 用执行器集工厂方法进行配置。
* <p>
* Thread pools address two different problems: they usually provide improved performance when executing large numbers of
* asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and managing the
* resources, including threads, consumed when executing a collection of tasks.
* Each {@code ThreadPoolExecutor} also maintains some basic statistics, such as the number of completed tasks.
* 线程池解决两个了不同的问题:由于减少了每个任务的调用开销(减少了开销?嗯 ~ 可能是指线程的创建/销毁的开销),他们
* 通常用于在执行庞大数量的异步任务时增加/提高性能;并且在执行任务集时提供了一种绑定及管理消费资源(包括线程)的方法。
* 每个线程池执行器还维护着一定基础的统计信息,例如完成任务的数量。
* <p>
* To be useful across a wide range of contexts, this class provides many adjustable parameters and extensibility hooks. However,
* programmers are urged to use the more convenient {@link Executors} factory methods
* {@link Executors#newCachedThreadPool} (unbounded thread pool, with automatic thread reclamation),
* {@link Executors#newFixedThreadPool} (fixed size thread pool) and
* {@link Executors#newSingleThreadExecutor} (single background thread),
* that preconfigure settings for the most common usage scenarios. Otherwise, use the following guide when manually configuring
* and tuning this class:
* 为了在广泛的上下文中发挥作用,这个类提供了许多可调参数和扩展钩子。然而,程序员被敦促使用更方便的执行器集工厂方法
* Executors#newCachedThreadPool(无界线程池,具有自动线程回收)、
* Executors#newFixedThreadPool(固定大小的线程池)和
* Executors#newSingleThreadExecutor(单个后台线程),
* 它们为最常见的使用场景预配置设置。否则,在手动配置和调优该类时使用以下指南:
* TODO 虽说文中极力推荐在使用Executors来进行线程池的创建,但实际上在现实开发中我们并不推荐这么做。因为上述几个创建
* TODO 线程池的方式都会消耗大量的资源(或是大量的线程、或是庞大的队列),而在现实开发中线程池又往往要专项专用,因此
* TODO 可能会创建很多个线程池,从而非常容易导致OOM。实际开发过程中,如果需要设计创建线程池的地方,都会推荐使用线
* TODO 程自身的构造方法采用与现实场景相匹配的参数进行创建。
* <dl>
* <dt>Core and maximum pool sizes</dt>
* <dt>核心及最大池大小</dt>
*
* <dd>
* A {@code ThreadPoolExecutor} will automatically adjust the pool size (see {@link #getPoolSize}) according to the bounds set
* by corePoolSize (see {@link #getCorePoolSize}) and maximumPoolSize (see {@link #getMaximumPoolSize}).
* 线程池执行器将根据【核心池大小】和【最大池大小】设置的边界自动调整池的大小。
* <p>
* When a new task is submitted in method {@link #execute(Runnable)}, and fewer than corePoolSize threads are running, a new
* thread is created to handle the request, even if other worker threads are idle. If there are more than corePoolSize but less
* than maximumPoolSize threads running, a new thread will be created only if the queue is full. By setting corePoolSize and
* maximumPoolSize the same, you create a fixed-size thread pool. By setting maximumPoolSize to an essentially unbounded value
* such as {@code Integer.MAX_VALUE}, you allow the pool to accommodate an arbitrary number of concurrent tasks. Most
* typically, core and maximum pool sizes are set only upon construction, but they may also be changed dynamically using {@link
* #setCorePoolSize} and {@link #setMaximumPoolSize}. </dd>
* 当在execute(Runnable task)方法中提交一个新任务,并且运行线程数少于【核心池大小】时,即使其他工作线程空闲,也会创建一个
* 新线程来处理请求。如果运行线程数大于【核心池大小】但小于【最大池大小】,则只有在队列已满时才会创建新线程。通过将"核心池
* 大小"和【最大池大小】设置相同,可以创建固定大小的线程池。通过将【最大池大小】设置为一个本质上不受限制的值时(例如int类型
* 的最大值)允许池容纳任意数量的并发任务。最典型的是,核心和最大池大小可在构造时设置,但也可以使用setCorePoolSize()方
* 法和setMaximumPoolSize()方法动态更改它们。
* </dd>
*
* <dt>On-demand construction</dt>
* <dt>按需构建(即根据实际的场景设置合适的线程数及队列大小)</dt>
*
* <dd>
* By default, even core threads are initially created and started only when new tasks arrive, but this can be overridden
* dynamically using method {@link #prestartCoreThread} or {@link #prestartAllCoreThreads}. You probably want to prestart
* threads if you construct the pool with a non-empty queue.
* 默认情况下,虽然核心线程只在新任务到达时才初始的创建和启动,但这可以使用prestartCoreThread()方法或
* prestartAllCoreThreads()方法动态覆盖。如果使用非空队列构造池,可能需要预启动线程。
* </dd>
*
* <dt>Creating new threads</dt>
* <dt>创建新的线程</dt>
*
* <dd>
* New threads are created using a {@link ThreadFactory}. If not otherwise specified, a{@link Executors#defaultThreadFactory}
* is used, that creates threads to all be in the same {@link ThreadGroup} and with the same {@code NORM_PRIORITY} priority
* and non-daemon status. By supplying a different ThreadFactory, you can alter the thread's name, thread group, priority,
* daemon status, etc. If a {@code ThreadFactory} fails to create a thread when asked by returning null from {@code newThread},
* the executor will continue, but might not be able to execute any tasks. Threads should possess the "modifyThread"
* {@code RuntimePermission}. If worker threads or other threads using the pool do not possess this permission, service may be
* degraded: configuration changes may not take effect in a timely manner, and a shutdown pool may remain in a state in which
* termination is possible but not completed.
* 使用线程工厂创建新线程。如果没有特别指定,则使用Executors(执行器集)类的defaultThreadFactory,它创建的线程都在同
* 一个线程组中,具有相同的NORM_PRIORITY(5)优先级和非守护状态。通过提供不同的线程工厂,您可以更改线程的名称、线
* 程组、优先级、守护状态等。如果线程工厂调用newThread()方法返回null时表示创建线程失败,线程池将继续执行,但可能无法
* 执行任何任务(即任务会在队列中不断累积)。线程应该具有"modifyThread"(即可修改的能力,例如可以重新设置线程的名字、
* 优先级、是否是守护线程,以及令其中断、停止等,具体详细解释可查询RuntimePermission类中的注释)。如果使用该池的工作
* 线程或其他线程不具有此权限,则服务可能降级:配置更改可能无法以及时的方式生效,并且一个已被关闭的池可能保持在可以
* 终止但无法终止的状态(即如果线程池内的线程不具备可被修改能力,则对线程池的设置可能无法/及时生效,并且可能也无法关
* 闭线程池)。
* </dd>
*
* <dt>Keep-alive times</dt>
* <dt>持续存活时间</dt>
*
* <dd>
* If the pool currently has more than corePoolSize threads, excess threads will be terminated if they have been idle for more
* than the keepAliveTime (see {@link #getKeepAliveTime(TimeUnit)}). This provides a means of reducing resource consumption
* when the pool is not being actively used. If the pool becomes more active later, new threads will be constructed. This
* parameter can also be changed dynamically using method {@link #setKeepAliveTime(long, TimeUnit)}. Using a value of
* {@code Long.MAX_VALUE} {@link TimeUnit#NANOSECONDS} effectively disables idle threads from ever terminating prior to
* shut down. By default, the keep-alive policy applies only when there are more than corePoolSize threads. But method {@link
* #allowCoreThreadTimeOut(boolean)} can be used to apply this time-out policy to core threads as well, so long as the
* keepAliveTime value is non-zero.
* 如果线程池当前有超过【核心池大小】的线程,并且它们的空闲时间超过持续存活时间,则额外线程将被终止。这提供了一种在池
* 没有被积极使用时减少资源消耗的方法。如果池稍后变得更加活跃,将会构造新的线程。该参数也可以使用setKeepAliveTime()
* 方法动态更改。使用值long类型的最大值及纳秒单位可以有效地禁止空闲线程在关闭之前终止(因为持续存活时间被设置的很长,
* 基本上不会因为超时被回收)。默认情况下,只有当线程数超过【核心池大小】时,才会应用持续存活策略(毕竟该参数是给非核
* 心线程使用的)。但是通过allowCoreThreadTimeOut()方法也可以将这个超时策略应用到核心线程上,只要"持续存活时间"不为0
* 即可。
* </dd>
*
* <dt>Queuing</dt>
* <dt>队列</dt>
*
* <dd>
* Any {@link BlockingQueue} may be used to transfer and hold submitted tasks. The use of this queue interacts with pool
* sizing:
* 一个阻塞队列可能用于迁移和保存递交的任务。队列的使用影响与池的大小:
* <ul>
* <li>
* If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
* 如果运行的线程少于【核心池大小】, 执行器总是更喜欢新增一个新线程(执行任务)而不是(将任务)入队。
* </li>
* <li>
* If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
* 如果大于等于核心池大小的线程正在运行,线程池总是倾向于(将任务)入队,而不是添加一个新线程(执行任务)。
* </li>
* <li>
* If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task
* will be rejected.
* 如果请求无法入队(即队列已满),则创建一个新线程(执行任务),除非该线程超过最大池大小,在这种情况下,任务将被
* 拒绝。
* </li>
* </ul>
* <p>
* There are three general strategies for queuing:
* 入队一般有三种策略:
* <ol>
* <li>
* <em> Direct handoffs.</em> A good default choice for a work queue is a {@link SynchronousQueue} that hands off tasks to
* threads without otherwise holding them. Here, an attempt to queue a task will fail if no threads are immediately available
* to run it, so a new thread will be constructed. This policy avoids lockups when handling sets of requests that might have
* internal dependencies. Direct handoffs generally require unbounded maximumPoolSizes to avoid rejection of new submitted
* tasks. This in turn admits the possibility of unbounded thread growth when commands continue to arrive on average faster
* than they can be processed.
* 直接传递。工作队列一个很好的默认选择是同步队列类,它将任务迁移给线程,而不保留它们。在这里,如果没有立即可用的
* 线程来运行任务,那么对任务进行入队的尝试将失败,因此将构造一个新线程(如果池线程没有达到最大数量)。在处理可能
* 具有内部依赖关系的请求集时,此策略避免了死锁。直接传递通常需要配合无限制的最大池大小(即无限制的线程数量),以
* 避免新提交的任务被拒绝。当命令的平均到达速度持续高于处理速度时,这反过来又承认了无限线程增长的可能性(即导致线
* 程池中的线程无限增长)。
* </li>
* <li>
* <em> Unbounded queues.</em> Using an unbounded queue (for example a {@link LinkedBlockingQueue} without a predefined
* capacity) will cause new tasks to wait in the queue when all corePoolSize threads are busy. Thus, no more than
* corePoolSize threads will ever be created. (And the value of the maximumPoolSize therefore doesn't have any effect.) This
* may be appropriate when each task is completely independent of others, so tasks cannot affect each others execution;
* for example, in a web page server. While this style of queuing can be useful in smoothing out transient bursts of requests,
* it admits the possibility of unbounded work queue growth when commands continue to arrive on average faster than they
* can be processed.
* 无界队列。使用无界队列(例如没有预指定容量的链接阻塞队列)将导致在所有核心线程忙碌的状态下新任务在队列中等待。
* 因此,不会创建超过核心池大小的线程。(最大数量池大小没有任何影响/作用)当每个任务完全独立于其它任务时,这可能
* 是合适的,因为任务不会影响其它任务执行;例如,在网络服务中。虽然这种队列类型在平滑短暂的请求爆发方面很有用(即
* 突然有很多的执行时间较短的网络请求),但当命令的平均到达速度持续高于它们的处理速度时,它也承认了无限工作队列增
* 长的可能性(即导致队列中任务的无限堆积)。
* </li>
* <li>
* <em>Bounded queues.</em> A bounded queue (for example, an {@link ArrayBlockingQueue}) helps prevent resource
* exhaustion when used with finite maximumPoolSizes, but can be more difficult to tune and control. Queue sizes and
* maximum pool sizes may be traded off for each other: Using large queues and small pools minimizes CPU usage, OS
* resources, and context-switching overhead, but can lead to artificially low throughput. If tasks frequently block (for
* example if they are I/O bound), a system may be able to schedule time for more threads than you otherwise allow. Use of
* small queues generally requires larger pool sizes, which keeps CPUs busier but may encounter unacceptable scheduling
* overhead, which also decreases throughput.
* 有界队列。当使用有限的maximumPoolSizes(最大数量池大小)参数时,有界队列(例如数组阻塞队列)有助于防止资源耗
* 尽,但可能更难调优和控制。队列大小和最大池大小可以相互权衡:使用大队列和小池可以最小化CPU使用、操作系统资源和
* 上下文切换开销,但可能导致人为的低吞吐量。如果任务频繁阻塞(例如,它们受I/O限制),系统可能会为超出您允许的更
* 多线程安排时间。使用小队列通常需要更大的池大小,这会使CPU更繁忙,并且可能会遇到不可接受的调度开销,这也会降低
* 吞吐量。
* </li>
* </ol>
* </dd>
*
* <dt>Rejected tasks</dt>
* <dt>拒绝任务</dt>
*
* <dd>
* New tasks submitted in method {@link #execute(Runnable)} will be <em>rejected</em> when the Executor has been shut
* down, and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is saturated.
* In either case, the {@code execute} method invokes the
* {@link RejectedExecutionHandler#rejectedExecution(Runnable, ThreadPoolExecutor)} method of its
* {@link RejectedExecutionHandler}. Four predefined handler policies are provided:
* 当执行器已经关闭,或者执行器对最大线程和工作队列容量使用有限的边界,并且已经饱和时,在execute(Runnable task)方
* 法中提交的新任务将被拒绝。在这两种情况下,execute(Runnable task)方法将调用拒绝执行处理器的rejectedExecution()方法。
* 提供了四个预定义的处理程序策略:
* <ol>
* <li>
* In the default {@link AbortPolicy}, the handler throws a runtime {@link RejectedExecutionException} upon rejection.
* 在默认的"中止策略"中,处理器在拒绝后抛出一个运行时拒绝执行异常。
* </li>
* <li>
* In {@link CallerRunsPolicy}, the thread that invokes {@code execute} itself runs the task. This provides a simple feedback
* control mechanism that will slow down the rate that new tasks are submitted.
* 在"调用者运行策略"中,调用执行execute(Runnable task)方法的线程运行任务。这提供了一个简单的可以降低新任务提交速度
* 的反馈控制机制(更重要的是无需再担心任务的处理问题,即是放弃还是抛出异常)。
* </li>
* <li>
* In {@link DiscardPolicy}, a task that cannot be executed is simply dropped.
* 在"丢弃策略"中,无法执行的任务被简单地丢弃。
* </li>
* <li>
* In {@link DiscardOldestPolicy}, if the executor is not shut down, the task at the head of the work queue is dropped, and
* then execution is retried (which can fail again, causing this to be repeated.)
* 在"丢弃最老策略"中,如果执行器没有关闭,那么位于工作队列头部的任务将被丢弃,然后重试执行(这可能会再次失败,导
* 致重复执行)。
* </li>
* </ol>
* <p>
* It is possible to define and use other kinds of {@link RejectedExecutionHandler} classes. Doing so requires some care
* especially when policies are designed to work only under particular capacity or queuing policies.
* 可以定义和使用其它类型的拒绝执行处理器类。这样做需要注意,尤其当策略设计为仅在特定容量或入队策略下工作时。
* </dd>
*
* <dt>Hook methods</dt>
* <dt>钩子方法</dt>
*
* <dd>
* This class provides {@code protected} overridable {@link #beforeExecute(Thread, Runnable)} and
* {@link #afterExecute(Runnable, Throwable)} methods that are called before and after execution of each task. These can
* be used to manipulate the execution environment; for example, reinitializing ThreadLocals, gathering statistics, or adding
* log entries. Additionally, method {@link #terminated} can be overridden to perform any special processing that needs to
* be done once the Executor has fully terminated.
* 这个类提供了受保护的可重写的beforeExecute(Thread, Runnable)方法和afterExecute(Runnable, Throwable)方法,在每个任务
* 执行之前和之后调用它们。这些可以用来操纵执行环境;例如,重初始化线程本地集、收集统计信息或添加日志条目。此外,
* 可以重写terminated()方法来执行执行器完全终止后需要执行的任何特殊处理。
* <p>
* If hook or callback methods throw exceptions, internal worker threads may in turn fail and abruptly terminate.
* 如果钩子或回调方法抛出异常,内部工作线程可能依次失败并突然终止。
* </dd>
*
* <dt>Queue maintenance</dt>
* <dt>队列维护</dt>
*
* <dd>
* Method {@link #getQueue()} allows access to the work queue for purposes of monitoring and debugging. Use of this method
* for any other purpose is strongly discouraged. Two supplied methods, {@link #remove(Runnable)} and {@link #purge} are
* available to assist in storage reclamation when large numbers of queued tasks become cancelled.
* getQueue()方法允许出于监视和调试的目的访问工作队列。强烈反对将此方法用于任何其他目的。提供的两个方法remove()和
* purge()可用于在大量入队任务被取消时协助进行存储回收。
* </dd>
*
* <dt>Finalization</dt>
* <dt>终止</dt>
*
* <dd>
* A pool that is no longer referenced in a program <em>AND</em> has no remaining threads will be {@code shutdown}
* automatically. If you would like to ensure that unreferenced pools are reclaimed even if users forget to call {@link #shutdown},
* then you must arrange that unused threads eventually die, by setting appropriate keep-alive times, using a lower bound of
* zero core threads and/or setting {@link #allowCoreThreadTimeOut(boolean)}.
* 一个在程序中不再被引用且没有剩余线程的池将被自动关闭。如果您想确保即使用户忘记调用shutdown()方法的情况下未被引用的
* 池也会被回收,那您必须安排未使用的线程最终死亡,通过设置适当的保持存活时间,使用0个核心线程的下限和/或设置
* allowCoreThreadTimeOut()方法(该方法可令核心线程像非核心线程一样被超时回收)。
* </dd>
*
* </dl>
*
* <p>
* <b>Extension example</b>. Most extensions of this class override one or more of the protected hook methods. For example,
* here is a subclass that adds a simple pause/resume feature:
* 扩展的例子。这个类的大多数扩展会重写一个或更多受保护的钩子方法。例如,下面是一个子类,它添加了一个简单的暂停/继
* 续功能:
*
* <pre> {@code
* class PausableThreadPoolExecutor extends ThreadPoolExecutor {
* // 是否暂停
* private boolean isPaused;
* // 用于控制暂停的可重入锁。
* private ReentrantLock pauseLock = new ReentrantLock();
* // 条件,用于阻塞线程。
* private Condition unpaused = pauseLock.newCondition();
*
* public PausableThreadPoolExecutor(...) { super(...); }
*
* protected void beforeExecute(Thread t, Runnable r) {
* // 调用父类的beforeExecute()方法。
* super.beforeExecute(t, r);
* // 加锁。
* pauseLock.lock();
* try {
* // 无限循环,当为isPaused(是否暂定)字段值true时令当前线程陷入等待状态。这里使用循环是为了防止在线程被
* // 唤醒后isPaused(是否暂定)字段值再次变为true的情况。
* while (isPaused)
* // 等待。
* unpaused.await();
* } catch (InterruptedException ie) {
* // 响应中断。
* t.interrupt();
* } finally {
* // 解锁。
* pauseLock.unlock();
* }
* }
*
* public void pause() {
* pauseLock.lock();
* try {
* // 暂停。
* isPaused = true;
* } finally {
* pauseLock.unlock();
* }
* }
*
* public void resume() {
* pauseLock.lock();
* try {
* // 中断暂停,并唤醒所有的线程。
* isPaused = false;
* unpaused.signalAll();
* } finally {
* pauseLock.unlock();
* }
* }
* }}</pre>
*
* @author Doug Lea
* @Description: 线程池执行器类
* @since 1.5
*/
public class ThreadPoolExecutor extends AbstractExecutorService {
/**
* The main pool control state, ctl, is an atomic integer packing two conceptual fields workerCount, indicating the effective
* number of thread runState, indicating whether running, shutting down etc.
* 主池控制状态ctl是一个来封装两个概念字段原子整数。workerCount(工作者总数):表示有效的/运行中的线程数量;
* runState(运行状态):表示是否运行中,关闭等等。
* <p>
* 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.
* 为了封装它们(即上文所讲的两个概念字段)为一个int类型字段,我们限制workerCount(工作者总数)为(2^29)-1(大约5
* 亿)个线程,而不是(2^31)-1 (20亿)个线程。如果这在未来一直是一个问题/争论点,该变量可改变为AtomicLong(原子大整
* 数)类,并调解下面的shift/mask常量。但直到需要产生(即问题出现之前),使用int类型的代码会更快更简单一点。
* <p>
* 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(工作者总数)是已经允许开始和不允许停止的工作者(线程)数量。该值可能短暂地不同于实际存活线程数量,
* 例如当线程工厂在被要求创建一个线程时失败,以及当正在退出的线程在终止之前依然执行薄记(薄记?)。用户可见池大小
* 被上报作为工作者集合的当前大小。
* <p>
* The runState provides the main lifecycle control, taking on values:
* runState(运行状态)提供主要的生命周期控制,呈现值:
* <p>
* 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
* 整理中:所有任务已终止,工作者总数为0,转换到整理中状态的线程将运行terminated()钩子方法
* TERMINATED: terminated() has completed
* 已终止:terminated()方法执行完成。
* <p>
* 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:
* 这些值的数字顺序很重要,以允许顺序比较。runState(运行状态)随时间增加,但不需要命中每个状态,转变(链路)如下:
* <p>
* RUNNING -> SHUTDOWN
* 运行中 -> 关闭
* On invocation of shutdown(), perhaps implicitly in finalize()
* 可能在finalize()方法中隐式的调用shutdown()方法
* (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()钩子方法已完成
* <p>
* Threads waiting in awaitTermination() will return when the state reaches TERMINATED.
* 线程在awaitTermination()方法中等待,当状态到达已终止时返回。
* <p>
* 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).
* 查明状态从关闭转变为整理中没有想象中简单,因为队列可能在关闭状态期间从非空变为空(反之亦然),但只有在看到队列
* 为空后看到workerCount(工作者总数)为0(有时需要重新检查——参见下文),我们才能终止。
*
* @Description: 名称:主池控制状态
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:用于记录当前线程池执行器中的运行状态及线程数量。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
/**
* @Description: 名称:总数位
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:用于计算容量及各种运行状态。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static final int COUNT_BITS = Integer.SIZE - 3;
/**
* @Description: 名称:容量
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:记录工作者的最大容量,值为2 ^ 29 - 1。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:该值通过1向左位移29位再减1获取,1的二进制表示为:
* @Description: 0000 0000 0000 0000 0000 0000 0000 0001
* @Description: 向左位移29位后为:
* @Description: 0010 0000 0000 0000 0000 0000 0000 0000
* @Description: 减1后为:
* @Description: 0001 1111 1111 1111 1111 1111 1111 1111
* @Description: 故该值为2 ^ 29 - 1。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
//运行状态保存在高位中(即保存在32中钱3位中)
/**
* @Description: 名称:运行中
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:表示当前线程池执行器为RUNNING(运行中)状态,值为-2 ^ 29。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:该值通过-1向左位移29位获取,-1的二进制表示为:
* @Description: 1111 1111 1111 1111 1111 1111 1111 1111
* @Description: 向左位移29位后为:
* @Description: 1110 0000 0000 0000 0000 0000 0000 0000
* @Description: 故该值为-2 ^ 29。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static final int RUNNING = -1 << COUNT_BITS;
/**
* @Description: 名称:关闭
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:表示当前线程池执行器为SHUTDOWN(关闭)状态,值为0。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:该值通过0向左位移29位获取,0的二进制表示为:
* @Description: 0000 0000 0000 0000 0000 0000 0000 0000
* @Description: 向左位移29位后为:
* @Description: 0000 0000 0000 0000 0000 0000 0000 0000
* @Description: 故该值为0。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static final int SHUTDOWN = 0 << COUNT_BITS;
/**
* @Description: 名称:停止
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:表示当前线程池执行器为STOP(停止)状态,值为2 ^ 29。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:该值通过1向左位移29位获取,1的二进制表示为:
* @Description: 0000 0000 0000 0000 0000 0000 0000 0001
* @Description: 向左位移29位后为:
* @Description: 0010 0000 0000 0000 0000 0000 0000 0000
* @Description: 故该值为2 ^ 29。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static final int STOP = 1 << COUNT_BITS;
/**
* @Description: 名称:整理中
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:表示当前线程池执行器为STOP(停止)状态,值为2 ^ 30。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:该值通过2向左位移29位获取,2的二进制表示为:
* @Description: 0000 0000 0000 0000 0000 0000 0000 0010
* @Description: 向左位移29位后为:
* @Description: 0100 0000 0000 0000 0000 0000 0000 0000
* @Description: 故该值为2 ^ 30。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static final int TIDYING = 2 << COUNT_BITS;
/**
* @Description: 名称:已终止
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:表示当前线程池执行器为TERMINATED(已终止)状态,值为2 ^ 30 + 2 ^ 29。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:该值通过3向左位移29位获取,3的二进制表示为:
* @Description: 0000 0000 0000 0000 0000 0000 0000 0011
* @Description: 向左位移29位后为:
* @Description: 0110 0000 0000 0000 0000 0000 0000 0000
* @Description: 故该值为2 ^ 30 + 2 ^ 29。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static final int TERMINATED = 3 << COUNT_BITS;
/**
* @Description: 名称:运行状态
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:计算运行状态值。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法首先将CAPACITY(容量)字段值进行位非运算得到中间值,随后令传入的状态参数与中间值进行位
* @Description: 与运算得到当前线程池执行器的运行状态,CAPACITY(容量)字段值为:
* @Description: 0001 1111 1111 1111 1111 1111 1111 1111
* @Description: 进行位非运算后为:
* @Description: 1110 0000 0000 0000 0000 0000 0000 0000
* @Description: 该值与状态参数进行位与运算后,可使结果值的后29位强制为0,只保留原本的前3位值,从而得到标准的运行
* @Description: 状态值。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
// Packing and unpacking ctl
// 封装及解封装ctl
private static int runStateOf(int c) {
return c & ~CAPACITY;
}
/**
* @Description: 名称:工作者总数
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:计算工作者总数。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法将传入的状态参数与CAPACITY(容量)字段值进行位与运算得到工作者总数,CAPACITY(容量)
* @Description: 字段值为:
* @Description: 0001 1111 1111 1111 1111 1111 1111 1111
* @Description: 该值与状态参数进行位与运算后,可使结果值的前3位强制为0,只保留原本的后29位值,从而得工作者总数。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static int workerCountOf(int c) {
return c & CAPACITY;
}
/**
* @Description: 名称:主池控制状态
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:计算主池控制状态值。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法将传入的运行状态参数与工作者总数参数进行位与运算得到主池控制状态。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
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.
* 位字段访问者不需要解封装主池控制状态。这依赖于位布局和工作者总数永远不为负(即不需要将主池运行状态进行解封装获
* 取标准的运行状态后再进行操作,因此运行状态信息保存在高位,可以不受低位的影响)。
*/
/**
* @Description: 名称:运行者状态小于
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:判断指定运行状态参数c是否小于指定运行状态参数s,是则返回true;否则返回false。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法通过直接比较两个传入的运行状态参数得到结果。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static boolean runStateLessThan(int c, int s) {
return c < s;
}
/**
* @Description: 名称:运行者状态至少
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:判断指定运行状态参数c是否大于等于指定运行状态参数s,是则返回true;否则返回false。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法通过直接比较两个传入的运行状态参数得到结果。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static boolean runStateAtLeast(int c, int s) {
return c >= s;
}
/**
* @Description: 名称:是否运行中
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:判断指定运行状态参数是否为RUNNING(运行中),是则返回true;否则返回false。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法通过直接判断指定运行状态参数值是否小于SHUTDOWN(关闭)得到结果。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static boolean isRunning(int c) {
return c < SHUTDOWN;
}
/**
* Attempts to CAS-increment the workerCount field of ctl.
* 尝试CAS递增主池运行状态的工作者总数。
*
* @Description: 名称:CAS递增工作者总数
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:通过CAS操作递增工作者总数,并返回是否成功。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法直接通过CAS操作将工作者总数在原有基础上加1。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private boolean compareAndIncrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect + 1);
}
/**
* Attempts to CAS-decrement the workerCount field of ctl.
* 尝试CAS递减主池运行状态的工作者总数。
*
* @Description: 名称:CAS递减工作者总数
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:通过CAS操作递减工作者总数,并返回是否成功。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法直接通过CAS操作将工作者总数在原有基础上减1。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
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.
* 递减主池运行状态的工作者总数。只在线程突然终止时调用(看processWorkerExit()方法)。其它递减在getTask()方法
* 中执行。
*
* @Description: 名称:递减工作者总数
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:循环通过CAS操作递减工作者总数,直至成功递减为止。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法死循环调用CAS操作将工作者总数在原有基础上减1,直至成功递减后停止。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private void decrementWorkerCount() {
do {
} while (!compareAndDecrementWorkerCount(ctl.get()));
}
/**
* 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.
* 该队列被用于持有任务和传递工作者。我们没必要使用工作队列的poll()方法返回null来表示工作队列为空,如果队列为空,可
* 仅仅依赖于isEmpty()方法(我们必须这样做,例如,当决定是否从SHUTDOWN(关闭)转变为TIDYING(整理中))。这适用
* 于指定目标队列,例如延迟队列,其poll()方法允许返回null,即使它可能稍后当延迟到期时返回非null。
*
* @Description: 名称:工作队列
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:持有任务及传递工作者线程。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private final BlockingQueue<Runnable> workQueue;
/**
* 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方法中避免非必要的中断爆发,特别是在关闭期间。否则需要并发地中断还未中断的正在退出的线程。它
* 还简化了部分最大池大小的关联统计薄记。我们还在shutdown()和shutdownNow()方法中持有主锁,处于当分开地检查中断和实
* 际中断中的权限时确定工作者集合是否稳定的目的。
* TODO 完全看不懂在说些什么...
*
* @Description: 名称:主锁
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:保证程序的线程安全。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private final ReentrantLock mainLock = new ReentrantLock();
/**
* Set containing all worker threads in pool. Accessed only when holding mainLock.
* 集合包含池中的所有工作者线程。只当持有主锁的时访问。
*
* @Description: 名称:工作者集合
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:保存当前线程池执行器中所有的工作者线程。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private final HashSet<Worker> workers = new HashSet<Worker>();
/**
* Wait condition to support awaitTermination
* 等待条件用于支持awaitTermination()方法
*
* @Description: 名称:终止条件
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:保存等待当前线程池执行器终止的线程。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private final Condition termination = mainLock.newCondition();
/**
* Tracks largest attained pool size. Accessed only under mainLock.
* 跟踪最大获取池大小。只当持有主锁的时访问。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 最大池大小
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 保存当前线程池执行器最多一次线程的总数。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
private int largestPoolSize;
/**
* Counter for completed tasks. Updated only on termination of worker threads. Accessed only under mainLock.
* 已完成任务计数器。只被已终止的工作者线程更新。只当持有主锁的时访问。
*
* @Description: 名称:已完成任务总数
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:保存当前线程池执行器已执行完成的任务总数。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
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(Runnable firstTask, boolean core)方法)。所有调用者必须准备好
* addWorker(Runnable firstTask, boolean core)方法失败,这可能反映了系统或用户限制线程数量的策略。即使它没有被看做是
* 一个错误,但线程创建失败也可能导致新任务被拒绝或已存在的任务被卡在队列中。
* <p>
* 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.
* 即使面对例如OOM一样的错误我们也进一步的维持池中的不变量(可能在尝试线程期间抛出)。由于需要在Thread.start中分
* 配一个本地栈,并且用户希望关闭清理池以进行清理,因此如此错误是颇为普通/常见的。可能会有足够的内存供清理代码完成,
* 而不会遇到另一个OutOfMemoryError(意思是即使遭遇了OOM,大概率也会有足够的内存来执行清理,不会在清理过程中遭遇
* 新的OOM)。
*
* @Description: 名称:线程工厂
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:为当前线程池执行器创建线程。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private volatile ThreadFactory threadFactory;
/**
* Handler called when saturated or shutdown in execute.
* 当执行饱和或关闭时调用处理器
*
* @Description: 名称:拒绝执行处理器
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:当当前线程池执行器已关闭或其队列已满时用于对新递交的任务进行处理。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
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.
* 等待工作的闲置线程的纳秒超时时间。当有超过【核心池大小】的线程存在或如果【允许核心线程超时】为ture时会使用超时
* 时间。否则线程会永久等待新任务。
*
* @Description: 名称:持续存活时间
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:记录当前线程池执行器中线程的闲置持续存活时间,当线程的闲置时间超过持续存活时间时线程会被回
* @Description: 收。该值默认只对非核心线程有效,但如果允许核心线程超时"为true则对核心线程也有效。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
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,核心线程使用【持续存活时间】来超时等待工作。
*
* @Description: 名称:允许核心线程超时
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:记录当前线程池执行器中的核心线程是否允许因为超时而回收。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
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.
* 核心池大小是工作者保持存活的最小值(并且不允许超时),除非【允许核心线程超时】被设置为true,这种情况下最小限度
* 为0。
*
* @Description: 名称:核心池大小
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:记录当前线程池执行器所允许创建的最大核心线程数量。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private volatile int corePoolSize;
/**
* Maximum pool size. Note that the actual maximum is internally bounded by CAPACITY.
* 最大池大小。注意:实现最大值被内部【容量】限制。
*
* @Description: 名称:最大池大小
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:记录当前线程池执行器所允许创建的最大线程数量。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:线程池执行器所允许创建的实际最大线程数量实际为【容量】,因此当【最大池大小】大于【容量】时最多只能
* @Description: 创建【容量】数量的线程。
*/
private volatile int maximumPoolSize;
/**
* The default rejected execution handler
* 默认拒绝执行处理器
*
* @Description: 名称:默认处理器
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:持有默认拒绝执行处理器的引用。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static final RejectedExecutionHandler defaultHandler = new 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()方法所需的许可。我们更需要(看checkShutdownAccess()方法)调用者有许可在工作者集合
* 中实际中断线程(由Thread.interrupt控制,其依赖于ThreadGroup.checkAccess,又依赖于SecurityManager.checkAccess)。
* 只当这些检查通过后关闭才会尝试进行。
* <p>
* 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()方法调用(看interruptIdleWorkers方法和interruptWorkers方法)都忽略安全异常,意味着已尝
* 试的中断会安静的失败(即不会抛出异常)。在关闭的情况下,它们不应该失败,除非安全管理器有不一致的策略,有时允许
* 访问一个线程且又是不允许。在如此情况下,实际中断线程失败可能无效或延迟完全的终止。其它interruptIdleWorkers()方法
* 的使用是会被警告的,并且实际失败中断将仅仅延迟对配置修改的回应,所以没有异常处理。
*
* @Description: 名称:关闭许可
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:持有许可的引用,只有设置该许可才可以关闭当前线程池执行器。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread");
/**
* The context to be used when executing the finalizer, or null.
* 当执行终止者或null时使用该上下文
*
* @Description: 名称:访问控制上下文
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:未知。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private final AccessControlContext acc;
/**
* 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).
* 工作类主要为线程正在运行的任务维护中断控制状态,沿着其它较小的薄记。该类适时地继承了抽象队列同步器类以简化获取
* 和释放围绕每个任务执行的锁。这可以防止试图唤醒正在等待任务的工作线程的中断,而不是中断正在运行的任务。我们实现
* 一个简单的非重入的相互独占锁而不是使用可重入锁,因为我们不要工作任务在它们调用类似于setCorePoolSize()的池控制方
* 法能够获取锁。此外,为阻止中断直到线程实际开始运行任务,我们初始化锁状态为负值,并在开始后清理它(在runWorker)。
*
* @Description: 名称:工作者类
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
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编译器警告。
*
* @Description: 名称:序列化ID
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:防止Java编译器警告。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private static final long serialVersionUID = 6138294804551838833L;
/**
* Thread this worker is running in. Null if factory fails.
* 在当前工作者中执行的线程。如果工厂(生产线程)失败则为null。
*
* @Description: 名称:线程
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:执行当前工作者中的任务,如果【线程工厂】创建线程失败则为null。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
final Thread thread;
/**
* Initial task to run. Possibly null.
* 初始运行的任务。可能为null。
*
* @Description: 名称:首个任务
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:持有当前工作者中的首个执行任务,可能为null。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
Runnable firstTask;
/**
* Per-thread task counter
* 每线程任务计数器
*
* @Description: 名称:已完成任务
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:记录当前工作者中线程已完成任务的总数。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
volatile long completedTasks;
/**
* Creates with given first task and thread from ThreadFactory.
* 根据指定首个任务和源自【线程工厂】的线程创建
*
* @param firstTask the first task (null if none) 首个任务(如果没有则为null)
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 工作者
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建指定首个任务的工作者,并为之创建工作者线程。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会将当前工作者的【状态】赋值为-1,表示其为运行。随后保存首个任务并使用【线程工厂】为之创
* @Description: 建工作者线程。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
Worker(Runnable firstTask) {
// inhibit interrupts until runWorker
// 已知中断直至运行工作者
setState(-1);
// 设置指定任务和执行线程。
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
/**
* Delegates main run loop to outer runWorker
* 代表主运行循环外部运行工作者
*
* @Description: 名称:运行
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:运行工作者。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:~
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
@Override
public void run() {
runWorker(this);
}
// Lock methods
// 锁方法
// The value 0 represents the unlocked state.
//
// The value 1 represents the locked state.
/**
* @Description: 名称:是否持有独占
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:判断当前线程是否已独占当前工作者,是则返回true;否则返回false。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法直接通过AQS的【状态】是否为0实现,事实上,由于工作者类是非可重入锁实现,因此【状态】
* @Description: 只有0和1两种可能。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
@Override
protected boolean isHeldExclusively() {
return getState() != 0;
}
/**
* @Description: 名称:尝试获取
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:令当前线程尝试独占当前工作者,成功则返回true;否则返回false。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法会通过CAS操作尝试将当前工作者的【状态】赋值为1,如果成功则将当前【独占拥有者线程】
* @Description: 赋值为当前线程以表示当前线程已独占了当前AQS,随后返回true;否则直接返回false。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
@Override
protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
/**
* @Description: 名称:尝试释放
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:令当前线程尝试解除对当前工作者的独占,成功则返回true;否则返回false。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法直接通过将当前工作者的【状态】及【独占拥有者线程】赋值0及null实现。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
@Override
protected boolean tryRelease(int unused) {
// 不用判断下是否是当前线程持有锁的吗?
setExclusiveOwnerThread(null);
setState(0);
return true;
}
/**
* @Description: 名称:加锁
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:令当前线程独占当前工作者。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法直接调用当前工作者的acquire(int arg)方法实现。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
public void lock() {
acquire(1);
}
/**
* @Description: 名称:尝试加锁
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:尝试令当前线程独占当前工作者,独占操作只会执行一次,成功则返回true;否则返回false。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法直接调用当前工作者的tryAcquire(int arg)方法实现。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
public boolean tryLock() {
return tryAcquire(1);
}
/**
* @Description: 名称:解锁
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:令当前线程结束对当前工作者的独占。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法直接调用当前工作者的release(int arg)方法实现。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
public void unlock() {
release(1);
}
/**
* @Description: 名称:是否加锁
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:判断当前线程是否已独占当前工作者。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法直接调用当前工作者的isHeldExclusively()方法实现。
* @Description: ----------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
public boolean isLocked() {
return isHeldExclusively();
}
/**
* @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
* @Description: 如果已开始则中断
* @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
* @Description: 中断当前工作者线程,无论其是否正在执行任务。
* @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
* @Description: 方法首先会判断当前工作者的【状态】是否大于等于0,否则直接结束,因为这意味着当前工作者尚未开
* @Description: 始用于执行任务。随后判断工作者线程是否存在,否则直接结束,因为这意味着线程工程未成功为当前工
* @Description: 作者创建用于执行任务的线程。接着再判断工作者线程是否已被中断,是则直接结束,因为已中断的线程
* @Description: 没有再次中断的必要;否则对之进行中断。
* @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
* @Description: 由于工作者线程可能没有"修改线程"许可,因此中断时可能抛出安全异常,需要在try块中捕捉并忽略该安
* @Description: 全异常,此时工作者线程将依旧处于未中断状态。
* @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
* @Description: TODO 疑问二:为什么工作者线程在没有"修改线程"许可的情况下,中断时抛出的安全异常会被直接忽略?
*/
void interruptIfStarted() {
Thread t;
// 方法首先会判断当前工作者的【状态】是否大于等于0,否则直接结束,因为这意味着当前工作者尚未开始用于执行任
// 务。随后判断工作者线程是否存在,否则直接结束,因为这意味着线程工程未成功为当前工作者创建用于执行任务的线
// 程。接着再判断工作者线程是否已被中断,是则直接结束,因为已中断的线程没有再次中断的必要;否则对之进行中断。
// 由于工作者线程可能没有"修改线程"许可,因此中断时可能抛出安全异常,需要在try块中捕捉并忽略该安全异常,此时
// 工作者线程将依旧处于未中断状态。
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
}
/*
* Methods for setting control state
* 设置控制状态的方法
*/
/**
* Transitions runState to given target, or leaves it alone if already at least the given target.
* 转变【运行状态】值指定目标,或者如果至少已是指定目标则不去管它。
*
* @param targetState the desired state, either SHUTDOWN or STOP(but not TIDYING or TERMINATED -- use tryTerminate
* for that)
* 期望的状态,要么是SHUTDOWN(关闭),要么是STOP(停止)(但不是TIDYING(整理中)或TERMINATED
* (已终止) -- 为此使用tryTerminate()方法)
* @Description: 名称:前进运行状态
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 作用:如果【运行状态】小于目标状态,则将【运行状态】修改为目标状态。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 逻辑:方法会判断当前线程池执行的【运行状态】是否大于目标状态,否则尝试通过CAS操作将【运行状态】
* @Description: 赋值为目标状态。该操作会循环不断的执行,直至【运行状态】成功被当前或其它线程赋值为大于等于目标状
* @Description: 态的状态为止。
* @Description: --------------------------------------------------------------------------------------------------------------------------------------
* @Description: 注意:~
*/
private void advanceRunState(int targetState) {
// 方法会判断当前线程池执行的【运行状态】是否大于目标状态,否则尝试通过CAS操作将【运行状态】赋值为目标状态。
// 该操作会循环不断的执行,直至【运行状态】成功被当前或其它线程赋值为大于等于目标状态的状态为止。
for (; ; ) {
int c = ctl.get();
if (runStateAtLeast(c, targetState) || ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
break;
}
}
/**
* Transitions to TERMINATED state if either (SHUTDOWN and pool and queue empty) or (STOP and pool empty). If otherwise
* eligible to terminate but workerCount is nonzero, interrupts an idle worker to ensure that shutdown signals propagate.
* This method must be called following any action that might make termination possible -- reducing worker count or removing
* tasks from the queue during shutdown. The method is non-private to allow access from ScheduledThreadPoolExecutor.
* 如果状态为已SHUTDOWN(关闭)并且池与队列都为空,或状态为STOP(停止)并且池为空,则转变状态为TERMINATED(
* 终止)。如果其它方面符合终止但【工作者总数】不为0,中断一个闲置工作者以确定关闭信号传播。该方法必须随着任意可
* 能导致终止的活动后调用 -- 在关闭期间减少工作者总数或从队列中移除任务。该方法不为私有以允许从计划线程池执行器中
* 访问。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 尝试终止
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 尝试终止当前线程池执行器。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法会判断当前线程池执行器的运行状态是否为RUNNING(运行),或者是否小于TIDYING(整理中),又或
* @Description: 者是否为SHUTDOWN(关闭)并且【工作队列】为null。如果上述三个条件满足任意一个则直接返回,因为这意
* @Description: 味着当前线程池执行器无法被终止或正在被终止。
* @Description: 在上述三个条件都不符合的情况下,说明当前线程池执行器在其它方面已经满足了终止的前提条件,继续判断
* @Description: 工作者总数是否为0。如果不为0,则当前线程池执行器还不可以终止,此时尝试中断一个闲置的工作者线程,
* @Description: 以传递当前线程池执行器将要终止的信号。
* @Description: 如果工作者总数为0,则当前线程池执行器可被终止,在加主锁的情况下通过CAS操作尝试将【运行状态】设置
* @Description: 为TIDYING(整理中)。之所以在加主锁的情况下还需要使用CAS操作是因为【主池控制状态】可能在判断的工
* @Description: 程中被修改,因此必须先比较,再设置。如果设置失败则跳转到方法的开头重新开始判断。
* @Description: 【运行状态】被成功设置为TIDYING(整理中)后,调用terminated()方法以在当前线程池执行器终止时执行自
* @Description: 定义逻辑。由于terminated()方法中执行的逻辑是自定义的,因此为了避免未知的异常打断整体流程,需要使用
* @Description: try块进行包括。
* @Description: 当terminated()方法正常/异常的执行结束后,最后将【运行状态】设置为TERMINATED(已终止)表示当前当
* @Description: 前线程池执行器彻底终止。并唤醒所有等待终止的线程令之返回。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
final void tryTerminate() {
for (; ; ) {
int c = ctl.get();
// 方法会判断当前线程池执行器的运行状态是否为RUNNING(运行),或者是否小于TIDYING(整理中),又或者是否为
// SHUTDOWN(关闭)并且【工作队列】为null。如果上述三个条件满足任意一个则直接返回,因为这意味着当前线程池
// 执行器无法被终止或正在被终止。
if (isRunning(c) || runStateAtLeast(c, TIDYING) || (runStateOf(c) == SHUTDOWN && !workQueue.isEmpty()))
return;
// Eligible to terminate
// 符合终止
// 在上述三个条件都不符合的情况下,说明当前线程池执行器在其它方面已经满足了终止的前提条件,继续判断工作者总
// 数是否为0。如果不为0,则当前线程池执行器还不可以终止,此时尝试中断一个闲置的工作者线程,以传递当前线程池
// 执行器将要终止的信号。
if (workerCountOf(c) != 0) {
interruptIdleWorkers(ONLY_ONE);
return;
}
// 如果工作者总数为0,则当前线程池执行器可被终止,在加主锁的情况下通过CAS操作尝试将【运行状态】设置为
// TIDYING(整理中)。之所以在加主锁的情况下还需要使用CAS操作是因为【主池控制状态】可能在判断的工程中被修
// 改,因此必须先比较,再设置。如果设置失败则跳转到方法的开头重新开始判断。
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
// 【运行状态】被成功设置为TIDYING(整理中)后,调用terminated()方法以在当前线程池执行器终止时执行
// 自定义逻辑。由于terminated()方法中执行的逻辑是自定义的,因此为了避免未知的异常打断整体流程,需要
// 使用try块进行包括。
terminated();
} finally {
// 当terminated()方法正常/异常的执行结束后,最后将【运行状态】设置为TERMINATED(已终止)表示当前
// 当前线程池执行器彻底终止。并唤醒所有等待终止的线程令之返回。
ctl.set(ctlOf(TERMINATED, 0));
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
/*
* Methods for controlling interrupts to worker threads.
* 控制中断工作者线程的方法
*/
/**
* If there is a security manager, makes sure caller has permission to shut down threads in general (see shutdownPerm). If
* this passes, additionally makes sure the caller is allowed to interrupt each worker thread. This might not be true even if
* first check passed, if the SecurityManager treats some threads specially.
* 如果有一个安全管理员,确保调用者在通常情况有许可来关闭线程(看shutdownPerm()方法)。如果该方法通过,更加确保调
* 用者允许中断每个工作者线程。如果安全安全管理员特别对待某些线程,即使首个判断通过该判断也可能不为true。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 检查关闭访问
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 检查当前线程池执行器的所有工作者线程是否具有"修改线程"许可。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会尝试获取安全管理员,并判断安全管理员是否存在。如果不存在则方法直接结束;否则为安全管
* @Description: 理员设置要检查的许可为"修改线程"许可。
* @Description: 在主锁的保护下,方法会遍历【工作者集合】,依次检查所有的工作者线程是否允许被修改,这个可以保证
* @Description: 工作者线程可以成功的被中断。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
private void checkShutdownAccess() {
// 获取系统的安全管理员,并判断当前线程是否具有modifyThread运行许可,没有则抛出安全异常。
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).
* 中断所有线程,即使线程活动(即正在执行任务)。忽略安全异常(在这种线程下某些线程可能保持未中断)
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 中断工作者集
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 中断当前线程池执行器中的所有工作者线程。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会加主锁,保证中断工作者线程的过程中线程安全。
* @Description: 随后遍历【工作者集合】,依次获取工作者,在确保工作者已启动/存在工作者线程/工作者线程未中断的情况
* @Description: 下中断工作者线程。
* @Description: 当所有可中断的工作者线程都执行了中断操作后,方法最后会解开主锁并结束。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: 由于工作者线程可能没有"修改线程"许可,因此中断时可能抛出安全异常,需要在try块中捕捉并忽略该安全异
* @Description: 常,此时工作者线程将依旧处于未中断状态。
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
private void interruptWorkers() {
// 方法首先会加主锁,保证中断工作者线程的过程中线程安全。
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 随后遍历【工作者集合】,依次获取工作者,在确保工作者已启动/存在工作者线程/工作者线程未中断的情况下中断工作
// 者线程。
for (Worker w : workers)
w.interruptIfStarted();
} finally {
// 当所有可中断的工作者线程都执行了中断操作后,方法最后会解开主锁并结束。
mainLock.unlock();
}
}
/**
* Interrupts threads that might be waiting for tasks (as indicated by not being locked) so they can check for termination or
* configuration changes. Ignores SecurityExceptions (in which case some threads may remain uninterrupted).
* 中断可能正在等待任务的线程(表示未被锁定),所以它们可以检查终止或配置改变。忽略安全异常(在这种情况下某些线程
* 可以保持未中断)。
*
* @param onlyOne If true, interrupt at most one worker. This is called only from tryTerminate when termination is otherwise
* enabled but there are still other workers. In this case, at most one waiting worker is interrupted to propagate
* shutdown signals in case all threads are currently waiting. Interrupting any arbitrary thread ensures that
* newly arriving workers since shutdown began will also eventually exit. To guarantee eventual termination, it
* suffices to always interrupt only one idle worker, but shutdown() interrupts all idle workers so that redundant
* workers exit promptly, not waiting for a straggler task to finish.
* 如果为true,最多中断一个工作者。只当终止在其它方式可用但依然有其它工作者时(即除了有工作者以外其它方
* 面都符合终止的条件)在tryTerminate()方法中调用。在这种情况下,最多中断一个等待中的工作者以传播关闭信
* 号至当前等待中的所有线程(即通过中断唤醒一个等待中的线程,并触发唤醒所有等待中的线程)。中断任意线
* 程以确保自关闭开始后新到达的工作者也将最终退出。为了保证最终终止,它可以经常只中断一个闲置工作者,
* shutdown()方法会中断所有的闲置工作者,因此多余的工作者会立即退出,不再等待一个掉队的任务结束。
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 中断闲置工作者集
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 中断当前线程池执行器中的所有或单个闲置工作者线程。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会加主锁,保证中断闲置工作者线程的过程中线程安全。
* @Description: 随后遍历【工作者集合】,依次获取工作者线程,判断其是否已中断。如果工作者线程尚未中断,则在成功将
* @Description: 工作者加锁的情况下中断工作者线程。此处对工作者加锁的作用是判断工作者线程是否闲置;成功加锁意味着
* @Description: 闲置,否则意味着活跃。
* @Description: 无论工作者线程原本是否中断、是否闲置、是否在中断时抛出安全异常,在以上单操作结束后都需要判断当前
* @Description: 方法是否只需要中断一个闲置工作者线程。如果是,则在首次单操作后循环就会终止,以满足最多只中断一个
* @Description: 闲置工作者线程的需求,否则就会不断循环直至所有的闲置工作者线程都被中断为止。
* @Description: 当闲置工作者线程执行了中断操作后,方法最后会解开主锁并结束。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: 由于工作者线程可能没有"修改线程"许可,因此中断时可能抛出安全异常,需要在try块中捕捉并忽略该安全异
* @Description: 常,此时工作者线程将依旧处于未中断状态。
*/
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();
}
}
/**
* Common form of interruptIdleWorkers, to avoid having to remember what the boolean argument means.
* interruptIdleWorkers()方法的普通格式,以避免必须记得布尔参数的含义。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 中断闲置工作者集
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 中断当前线程池执行器中的所有闲置工作者线程。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 与interruptIdleWorkers(boolean onlyOne)方法相同。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: 与interruptIdleWorkers(boolean onlyOne)方法相同。
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: 与interruptIdleWorkers(boolean onlyOne)方法相同。
*/
private void interruptIdleWorkers() {
interruptIdleWorkers(false);
}
private static final boolean ONLY_ONE = true;
/*
* Misc utilities, most of which are also exported to ScheduledThreadPoolExecutor
* 各式各样的公共资源,其中大部分导出至计划线程池执行器。
*/
/**
* Invokes the rejected execution handler for the given command. Package-protected for use by ScheduledThreadPoolExecutor.
* 为指定命令调用拒绝执行处理器。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 拒绝
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 调用当前线程池执行器的【拒绝执行处理器】执行指定命令。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
final void reject(Runnable command) {
handler.rejectedExecution(command, this);
}
/**
* Performs any further cleanup following run state transition on invocation of shutdown. A no-op here, but used by
* ScheduledThreadPoolExecutor to cancel delayed tasks.
* 在shutdown()方法调用及运行状态转变后执行任意进一步的清理。这里没有操作,但是被计划线程池执行器用来取消已延迟的
* 任务。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 在关闭时
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 在shutdown方法调用且当前线程池执行器转变为SHUTDOWN(关闭)后执行自定义操作。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
void onShutdown() {
}
/**
* State check needed by ScheduledThreadPoolExecutor to enable running tasks during shutdown.
* 计划线程池执行器需要检查状态以在关闭期间令运行中的任务可用。
*
* @param shutdownOK true if should return true if SHUTDOWN 如果当SHUTDOWN(关闭)时如果需要返回true则为true
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 是否运行或关闭
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 在shutdown方法调用且当前线程池执行器转变为SHUTDOWN(关闭)后执行自定义操作。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
final boolean isRunningOrShutdown(boolean shutdownOK) {
// 方法首先会获取当前线程池执行器的【运行状态】,随后判断【运行状态】是否为RUNNING(运行中)。如果是则返回
// true;否则在参数要求的情况下判断【运行状态】是否为SHUTDOWN(关闭)。是则返回true;否则返回false。
int rs = runStateOf(ctl.get());
return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
}
/**
* Drains the task queue into a new list, normally using drainTo. But if the queue is a DelayQueue or any other kind of queue
* for which poll or drainTo may fail to remove some elements, it deletes them one by one.
* 流失任务队列至一个新列表中,通常使用drainTo()方法。但如果队列时延迟队列或其它任意poll()或drainTo()方法可能失败移除
* 某些元素的队列,则它会一个接一个的删除它们(即逐个的从队列中移除元素并加入新列表中)。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 流失队列
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 将当前线程池执行器【任务队列】中任务转移至一个新列表中。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会实例化一个任务列表用于承载任务,随后调用【任务队列】的drainTo(Collection<? super E> c)方
* @Description: 法将其中的任务全部转移至任务列表中。
* @Description: 如果在转移之后【任务队列】中依然存有任务,则可能是因为并发新增了新任务或
* @Description: drainTo(Collection < ? super E > c)方法无法转移全部的任务,就例如延迟队列无法转移未延迟到期元素。在
* @Description: 这种情况下通过toArray(T a)方法获取【任务队列】中剩余任务的快照,随后遍历该快照将任务从【任务
* @Description: 队列】中移除并加入任务列表中。
* @Description: 当【任务队列】中所有的任务都转移至任务列表后,返回任务列表。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
private List<Runnable> drainQueue() {
// 方法首先会实例化一个任务列表用于承载任务,随后调用【任务队列】的drainTo(Collection<? super E> c)方法将其中的
// 任务全部转移至任务列表中。
BlockingQueue<Runnable> q = workQueue;
ArrayList<Runnable> taskList = new ArrayList<Runnable>();
q.drainTo(taskList);
// 如果在转移之后【任务队列】中依然存有任务,则可能是因为并发新增了新任务或drainTo(Collection<? super E> c)方法
// 无法转移全部的任务,就例如延迟队列无法转移未延迟到期元素。在这种情况下通过toArray(T【】 a)方法获取【任务队
// 列】中剩余任务的快照,随后遍历该快照将任务从【任务队列】中移除并加入任务列表中。
if (!q.isEmpty()) {
for (Runnable r : q.toArray(new Runnable[0])) {
if (q.remove(r))
taskList.add(r);
}
}
// 当【任务队列】中所有的任务都转移至任务列表后,返回任务列表。
return taskList;
}
/*
* Methods for creating, running and cleaning up after workers
* 工作者创建、运行以及清理的方法
*/
/**
* 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.
* 检查基于当前池状态和指定边界(核心和最大)能否新增一个新工作者。如果可以,则工作者总数将相应地调整,并且,如果
* 可能,一个新工作将创建和开始,运行参数任务作为其的首个任务。如果池已经停止或符合关闭,则当前方法会返回false。如
* 果当要求时线程工厂失败创建线程,则也会返回false。如果线程创建失败,要么由于线程工厂返回null,要么由于一个异常(
* 通常是在Thread.start()方法中抛出的OOM错误),我们彻底地回滚。
*
* @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.
* 新线程应该运行的首个任务(如果没有则为null)。当有比【核心池大小】更少的线程(在这种情况下我们经常
* 开始一个线程),或当队列已满(在这种情况下我们必须避免入队)时工作者会伴随一个初始首个任务创建(在
* execute())方法中)以避免入队。最初闲置线程通常通过【预开始核心线程】或取代垂死的工作者创建。
* @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).
* 如果为真则使用【核心池大小】作为边界,否则使用【最大池大小】作为边界。(这里使用布尔标志而不是一个
* 值来保证在检查其它池状态后最新值的读取)
* @return true if successful 如果成功则为true
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 新增工作者
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 为当前线程池执行器创建一个新工作者,新增成功则返回true;否则返回false。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会判断当前线程池执行器【运行状态】能否支持创建新工作者。方法通过【主池控制状态】获取【运
* @Description: 行状态】,判断当前线程池执行器是否为STOP(停止)/TIDYING(整理中)/TERMINATION(终止),以及在
* @Description: SHUTDOWN(关闭)的情况下是否已没有可执行的任务(包括首个任务以及【任务队列】中的任务)。如果是,
* @Description: 则当前线程池执行器便不允许/没必要在创建新工作者了,直接结束方法并返回false,表示创建工作者失败;
* @Description: 否则继续进行工作者的数量判断。
* @Description: 工作者数量判断是为了确保当前线程池执行器的【工作者总数】没有达到指定上限。方法首先会判断【工作者
* @Description: 总数】是否大于等于【容量】或【核心池大小】/【最大池大小】(根据参数选择),是则说明当前线程池执
* @Description: 行器的【工作者总数】已达上限,不允许在创建新工作者了,直接结束方法并返回false,表示创建工作者失败;
* @Description: 否则通过CAS操作递增 【工作者总数】。之所以先递增【工作者总数】而非先创建新工作者,是因为新工作的
* @Description: 创建是可以并发的,因此作为工作者能否创建的判断依据,【工作者总数】必须先于创建工作者之前更新,否
* @Description: 则会导致工作者重复创建/超出上限。同样由于并发的原因,递增【工作者总数】的CAS操作可能会失败,这种
* @Description: 情况下不会立即重试,而是会先判断【运行状态】是否发生了变化。是则将方法跳转至起点,即从判断当前线
* @Description: 程池执行器的【运行状态】能否支持创建新工作者处重新执行;否则从判断当前线程池执行器的【工作者总数】
* @Description: 是否达到指定上限处重新执行。从上述流程中可以发现的是:在创建新工作者期间【运行状态】是会发生并发
* @Description: 变化的。
* @Description: 成功递增【工作者总数】后,方法会正式创建新工作者。新工作者(及其工作者线程)被创建后,方法会判断
* @Description: 新工作者线程是否存在,因为【线程工程】创建工作者线程可能会失败。如果新工作者线存在,则继续在持有
* @Description: 主锁的情况下重新检查【运行状态】是否支持新增工作者,这是因为之前的流程中都没有加主锁,所以【运行
* @Description: 状态】可能已经并发的改变。除此之外还有一个原因就是【工作者集合】是HashMap(哈希映射)类对象,其
* @Description: 并不是线程安全的。如果【运行状态】支持新增,并且新工作者线程依然存活(不存活会抛出非法状态异常),
* @Description: 则将新工作者加入【工作者集合】中,更新【最大池大小】并启动新工作者线程(启动新工作者线程时可能会
* @Description: 抛出OOM错误),至此,工作者新增正式完成。而如果新工作线程创建失败/【运行状态】发生改变已不再支
* @Description: 持新增工作者/新工作者线程死亡抛出非法状态异常/新工作者线程启动失败抛出OOM错误,则说明新增工作者
* @Description: 失败,需要执行addWorkerFailed(Worker w)方法销毁创建的工作者并尝试终止当前线程池执行器。
* @Description: 当上述所有的流程执行结束,返回方法的执行结果,即新工作者是否创建成功。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: 通常情况下(新工作线程创建失败/【运行状态】发生改变已不再支持新增工作者/新工作者线程死亡抛出非法
* @Description: 状态异常),新增工作者失败是不会将工作者加入到【工作者集合】中的,但有一种情况例外,即新工作者线
* @Description: 程启动失败抛出OOM错误,因为新工作者线程启动位于将新工作者加入【工作者集合】之后。由此可以知道的
* @Description: 是【工作者集合】中所有的工作者都是存在工作者线程的,但工作者线程不一定处于启动的状态。
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (; ; ) {
// 方法首先会判断当前线程池执行器【运行状态】能否支持创建新工作者。方法通过【主池控制状态】获取【运行状态】,
// 判断当前线程池执行器是否为STOP(停止)/TIDYING(整理中)/TERMINATION(终止),以及在SHUTDOWN(关闭)
// 的情况下是否已没有可执行的任务(包括首个任务以及【任务队列】中的任务)。如果是,则当前线程池执行器便不允
// 许/没必要在创建新工作者了,直接结束方法并返回false,表示创建工作者失败;否则继续进行工作者的数量判断。
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 (; ; ) {
// 工作者数量判断是为了确保当前线程池执行器的【工作者总数】没有达到指定上限。方法首先会判断【工作者总数】
// 是否大于等于【容量】或【核心池大小】/【最大池大小】(根据参数选择),是则说明当前线程池执行器的【工作
// 者总数】已达上限,不允许在创建新工作者了,直接结束方法并返回false,表示创建工作者失败;否则通过CAS操
// 作递增 【工作者总数】。之所以先递增【工作者总数】而非先创建新工作者,是因为新工作的创建是可以并发的,
// 因此作为工作者能否创建的判断依据,【工作者总数】必须先于创建工作者之前更新,否则会导致工作者重复创建/
// 超出上限。同样由于并发的原因,递增【工作者总数】的CAS操作可能会失败,这种情况下不会立即重试,而是会先
// 判断【运行状态】是否发生了变化。是则将方法跳转至起点,即从判断当前线程池执行器的【运行状态】能否支持创
// 建新工作者处重新执行;否则从判断当前线程池执行器的【工作者总数】是否达到指定上限处重新执行。从上述流程
// 中可以发现的是:在创建新工作者期间【运行状态】是会发生并发变化的。
int wc = workerCountOf(c);
if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
// Re-read ctl
// 重读取【主池控制状态】
c = ctl.get();
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
// 由于【工作者总数】改变而失败,内部循环重试
}
}
// 成功递增【工作者总数】后,方法会正式创建新工作者。新工作者(及其工作者线程)被创建后,方法会判断新工作者线
// 程是否存在,因为【线程工程】创建工作者线程可能会失败。如果新工作者线存在,则继续在持有主锁的情况下重新检查
// 【运行状态】是否支持新增工作者,这是因为之前的流程中都没有加主锁,所以【运行状态】可能已经并发的改变。除此
// 之外还有一个原因就是【工作者集合】是HashMap(哈希映射)类对象,其并不是线程安全的。如果【运行状态】支持新
// 增,并且新工作者线程依然存活(不存活会抛出非法状态异常),则将新工作者加入【工作者集合】中,更新【最大池大
// 小】并启动新工作者线程(启动新工作者线程时可能会抛出OOM错误),至此,工作者新增正式完成。而如果新工作线程
// 创建失败/【运行状态】发生改变已不再支持新增工作者/新工作者线程死亡抛出非法状态异常/新工作者线程启动失败抛
// 出OOM错误,则说明新增工作者失败,需要执行addWorkerFailed(Worker w)方法销毁创建的工作者并尝试终止当前线程池
// 执行器。
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)) {
// precheck that t is startable
// 预检查是否可开始。
if (t.isAlive())
throw new IllegalThreadStateException();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
新工作者线程启动可能会抛出OOM错误。
t.start();
workerStarted = true;
}
}
} finally {
if (!workerStarted)
addWorkerFailed(w);
}
// 当上述所有的流程执行结束,返回方法的执行结果,即新工作者是否创建成功。
return workerStarted;
}
/**
* Rolls back the worker thread creation.
* 回滚工作者线程创建。
* - removes worker from workers, if present
* - 从【工作者集合】中移除工作者(如果存在)
* - decrements worker count
* - 递减工作者总数
* - rechecks for termination, in case the existence of this worker was holding up termination
* - 重检查终止,万一当前工作者的存在阻拦终止。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 新增工作者失败
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 当新增工作者失败时将创建的新工作者进行清理,并回滚在创建新工作者时执行的操作。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法会在加主锁的情况下执行,因为【工作者集合】并不是线程安全的。加锁后,将指定工作者从【工作者集
* @Description: 合】中移除(因为工作者线程启动时可能会抛出OOM错误导致新增工作者失败,这种情况下新工作者会存在于
* @Description: 【工作者集合】中),并递减【工作者总数】,随后尝试终止当前线程池执行器。这是因为工作者会存在于【
* @Description: 工作者集合】中可能会阻碍终止,因此在将之舍弃后需要重试终止。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
private void addWorkerFailed(Worker w) {
// 方法会在加主锁的情况下执行,因为【工作者集合】并不是线程安全的。加锁后,将指定工作者从【工作者集合】中移除
// (因为工作者线程启动时可能会抛出OOM错误导致新增工作者失败,这种情况下新工作者会存在于【工作者集合】中),
// 并递减【工作者总数】,随后尝试终止当前线程池执行器。这是因为工作者会存在于【工作者集合】中可能会阻碍终止,
// 因此在将之舍弃后需要重试终止。
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (w != null)
workers.remove(w);
decrementWorkerCount();
tryTerminate();
} finally {
mainLock.unlock();
}
}
/**
* 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(突然完成)参数被设置,否则假设【工作
* 者总数】已经被调整为退出账目。该方法会从【工作者集合】中移除工作者,并且可能终止池或在工作者线程因为用户任务
* 异常而退出/少于【核心池线程】的工作者在运行/队列不为空但没有工作者时替换工作者。
*
* @param w the worker 工作者
* @param completedAbruptly if the worker died due to user exception 如果工作者用于用户异常而死亡
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 处理工作者退出
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 处理当前工作者退出时需执行的【工作者总数】递减、将当前工作者从【工作者集合】中移除、重新启用当前
* @Description: 工作者等一系列操作。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会通过『突然完成』判断当前工作者是否是因为任务执行异常而退出。是则递减【工作者总数】。事
* @Description: 实上,无论是因为什么原因,在退出当前工作者时都是需要递减【工作者总数】的。但是如果是因为未获取到
* @Description: 任务而退出,则递减会在getTask(Worker w)方法中完成。因此此处只执行因为任务执行异常而退出时的【工作
* @Description: 者总数】递减。
* @Description: 【工作者总数】递减完成后,在主锁的保护下,当前工作者的【已完成任务】会被添加至线程池执行器的【已
* @Description: 完成任务总数】,随后当前工作者会从【工作者集合】中移除(移除后的当前工作者并不一定会被抛弃,根据
* @Description: 后续逻辑,其可能会被重新添加至【工作者集合】中),并解开主锁。
* @Description: 由于运行中的工作者线程可能会阻止shutdown()方法进行的终止,因此在当前工作者要求被退出后,需要尝试
* @Description: 终止当前线程池执行器。
* @Description: 无论当前线程池执行器的终止结果如何,接下来都要判断其【运行状态】是否小于STOP(停止),否则直接
* @Description: 结束,即抛弃当前工作者;是则说明当前线程池执行器还处于可继续执行的状态,因此当前工作者理论上应该
* @Description: 重新被启用,即递增【工作者总数】并将之加入到【工作者集合】中。但是在进行该操作之前,会先判断当前
* @Description: 工作者是否是因为获取不到新任务而退出。如果是,则需要判断当前线程池执行中【工作者总数】是否大于等
* @Description: 于理论上其应该持有的『最小线程总数』,如果是,则说明当前线程池执行器中的工作者以足够,当前工作者
* @Description: 无需在重新启用。『最小线程总数』的计算依赖【允许核心线程超时】,如果【允许核心线程超时】为true,
* @Description: 则该变量值为0;否则为当前的【核心池大小】。『最小线程总数』确定后,判断其是否为0,如果是,并且【
* @Description: 工作队列】不为空的话,则将之修改为1,因为在【工作队列】不为空的情况下,至少需要一个工作线程来执
* @Description: 行任务。随后继续判断当前【工作者总数】是否大于等于『最小线程总数』(一般情况下是不会大于的,但可
* @Description: 以通过setCorePoolSize(int corePoolSize)方法设置一个更小的新【核心池大小】,这种情况下就会出现大于的
* @Description: 情况),如果是,则直接返回,因为当前线程池执行器中已经存在有足够数量的工作者线程。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
private void processWorkerExit(Worker w, boolean completedAbruptly) {
// If abrupt, then workerCount wasn't adjusted
// 如果突然的,那么【工作者总数】不调整。
// 方法首先会通过『突然完成』判断当前工作者是否是因为任务执行异常而退出。是则递减【工作者总数】。事实上,无论
// 是因为什么原因,在退出当前工作者时都是需要递减【工作者总数】的。但是如果是因为未获取到任务而退出,则递减会
// 在getTask(Worker w)方法中完成。因此此处只执行因为任务执行异常而退出时的【工作者总数】递减。
if (completedAbruptly)
decrementWorkerCount();
// 【工作者总数】递减完成后,在主锁的保护下,当前工作者的【已完成任务】会被添加至线程池执行器的【已完成任务总
// 数】,随后当前工作者会从【工作者集合】中移除(移除后的当前工作者并不一定会被抛弃,根据后续逻辑,其可能会被
// 重新添加至【工作者集合】中),并解开主锁。
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
workers.remove(w);
} finally {
mainLock.unlock();
}
// 由于运行中的工作者线程可能会阻止shutdown()方法进行的终止,因此在当前工作者要求被退出后,需要尝试终止当前线程
// 池执行器。
tryTerminate();
// 无论当前线程池执行器的终止结果如何,接下来都要判断其【运行状态】是否小于STOP(停止),否则直接结束,即抛弃
// 当前工作者;是则说明当前线程池执行器还处于可继续执行的状态,因此当前工作者理论上应该重新被启用,即递增【工作
// 者总数】并将之加入到【工作者集合】中。但是在进行该操作之前,会先判断当前工作者是否是因为获取不到新任务而退出。
// 如果是,则需要判断当前线程池执行中【工作者总数】是否大于等于理论上其应该持有的『最小线程总数』,如果是,则说
// 明当前线程池执行器中的工作者以足够,当前工作者无需在重新启用。『最小线程总数』的计算依赖【允许核心线程超时】,
// 如果【允许核心线程超时】为true,则该变量值为0;否则为当前的【核心池大小】。『最小线程总数』确定后,判断其是否
// 为0,如果是,并且【工作队列】不为空的话,则将之修改为1,因为在【工作队列】不为空的情况下,至少需要一个工作线
// 程来执行任务。随后继续判断当前【工作者总数】是否大于等于『最小线程总数』,如果是,则直接返回,因为当前线程池
// 执行器中已经存在有足够数量的工作者线程。
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)
// replacement not needed
// 替换不需要的
return;
}
addWorker(null, false);
}
}
/**
* Performs blocking or timed wait for a task, depending on current configuration settings, or returns null if this worker
* must exit because of any of:
* 依赖当前设置的配置执行阻塞或定时等待任务,或者如果当前工作者因为下列原因必须退出则返回null
* 1. There are more than maximumPoolSize workers (due to a call to setMaximumPoolSize).
* 1. 有超过【最大池大小】的工作者(由于调用setMaximumPoolSize()方法)。
* 2. The pool is stopped.
* 2. 池已停止。
* 3. The pool is shutdown and the queue is empty.
* 3. 池已关闭并且队列为空。
* 4. This worker timed out waiting for a task, and timed-out
* 4. 工作者定时等待一个任务,并且超时
* workers are subject to termination (that is, {@code allowCoreThreadTimeOut || workerCount > corePoolSize}) both before
* and after the timed wait, and if the queue is non-empty, this worker is not the last thread in the pool.
* 工作者(即allowCoreThreadTimeOut || workerCount > corePoolSize)在定时等待之前/之后都受终止管制, 并且如果队列不
* 为空,则当前工作者不是池中的最后一个线程。
*
* @return task, or null if the worker must exit, in which case workerCount is decremented
* 任务,或者如果工作者必须退出,在这种情况下【工作者总数】会递减
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取任务
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 从【工作队列】中获取任务,如果当前线程池执行器不允许/无法获取到任务则返回null。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会进入死循环,循环中其会获取当前线程池执行器的【运行状态】。如果【运行状态】大于等于
* @Description: STOP(停止)或者大于等于SHUTDOWN(关闭)并且【工作队列】为空,则说明当前线程池执行器已经不允
* @Description: 许再获取任务了,直接递减【工作者总数】后返回null,表示当前工作者线程将被抛弃并且获取任务失败。
* @Description: 如果【运行状态】满足获取任务的条件,则获取当前线程池执行器的【工作者总数】。随后判断当前工作者线
* @Description: 程是否需要定时获取任务,这需要通过【允许核心线程超时】及【工作者总数】是否大于【核心池大小】判断。
* @Description: 如果满足两者的任意一个则意味着当前工作者线程需要在【持续存活时间】内获取任务。
* @Description: 确定是否定时获取任务后,判断【工作者总数】是否大于【最大池大小】(正常是不会出现该情况的,但如果
* @Description: 有线程调用了setMaximumPoolSize(int maximumPoolSize)方法的话就可能发生,因为新【最大值大小】可能小
* @Description: 于【工作者总数】)或者定时且超时的情况。如果有,则理论上当前工作者线程是需要被抛弃的,即当前方法
* @Description: 需要递减【工作者总数】并返回null。但由于并发的原因,执行该操作前还会继续判断是否存在【工作者总数】
* @Description: 大于1或【工作队列】为空的情况。如果没有,则当前工作者线程会被继续保留,因为当前线程池执行器中会
* @Description: 预保留一个工作者线程,以及在将当前工作者线程抛弃之前会竟可能的将之利用,即将【工作队列】中的所有
* @Description: 任务都耗尽之后再抛弃。
* @Description: 由于并发的原因,在抛弃当前线程时,即递减【工作者总数】时可能会失败,这种情况下会重新循环,即从判
* @Description: 断【运行状态】处重新运行。
* @Description: 在判定当前工作者线程允许获取获取任务的情况下,根据是否定时,使用"阻塞"或"超时"形式的移除/拿取方法
* @Description: 从【工作队列】中获取任务,如果获取到任务则直接返回;否则将『是否超时』设置为true("阻塞"形式的移
* @Description: 除/拿取方法正常情况下是不可能获取不到的)。如果在等待移除/拿取方法等待期间当前工作者线程被中断(
* @Description: 一般是因为被立即关闭的原因),则当前将『是否超时』设置为false。在没有正常获取到任务的情况下都需要
* @Description: 正常重新循环。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: TODO 为什么在【工作者总数】大于【最大池大小】或定时且超时的情况当前工作者线程需要在【工作者总数】
* @Description: TODO 大于1的情况下才可以被抛弃?
*/
private Runnable getTask() {
// Did the last poll() time out?
// 最后一次poll()是否超时了吗?
boolean timedOut = false;
for (; ; ) {
// 方法首先会进入死循环,循环中其会获取当前线程池执行器的【运行状态】。如果【运行状态】大于等于STOP(停止)
// 或者大于等于SHUTDOWN(关闭)并且【工作队列】为空,则说明当前线程池执行器已经不允许再获取任务了,直接
// 递减【工作者总数】后返回null,表示当前工作者线程将被抛弃并且获取任务失败。
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
// 只在必要时检查队列是否为空。
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
// 如果【运行状态】满足获取任务的条件,则获取当前线程池执行器的【工作者总数】。随后判断当前工作者线程是否
// 需要定时获取任务,这需要通过【允许核心线程超时】及【工作者总数】是否大于【核心池大小】判断。如果满足两
// 者的任意一个则意味着当前工作者线程需要在【持续存活时间】内获取任务。
int wc = workerCountOf(c);
// Are workers subject to culling?
// 工作者是否会被剔除?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
// 确定是否定时获取任务后,判断【工作者总数】是否大于【最大池大小】(正常是不会出现该情况的,但如果有线程
// 调用了setMaximumPoolSize(int maximumPoolSize)方法的话就可能发生,因为新【最大值大小】可能小于【工作者总
// 数】)或者定时且超时的情况。如果有,则理论上当前工作者线程是需要被抛弃的,即当前方法需要递减【工作者总
// 数】并返回null。但由于并发的原因,执行该操作前还会继续判断是否存在【工作者总数】大于1或【工作队列】为空
// 的情况。如果没有,则当前工作者线程会被继续保留,因为在【工作队列】不为空的情况下至少要保留一个用于执行
// 任务,以及在将当前工作者线程抛弃之前会竟可能的将之利用,即将【工作队列】中的所有任务都耗尽之后再抛弃。
// 由于并发的原因,在抛弃当前线程时,即递减【工作者总数】时可能会失败,这种情况下会重新循环,即从判断【运
// 行状态】处重新运行。
if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
// 在判定当前工作者线程允许获取获取任务的情况下,根据是否定时,使用"阻塞"或"超时"形式的移除/拿取方法从【工
// 作队列】中获取任务,如果获取到任务则直接返回;否则将『是否超时』设置为true("阻塞"形式的移除/拿取方法正
// 常情况下是不可能获取不到的)。如果在等待移除/拿取方法等待期间当前工作者线程被中断(一般是因为被立即关闭
// 的原因),则当前将『是否超时』设置为false。在没有正常获取到任务的情况下都需要正常重新循环。
try {
Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
/**
* Main worker run loop. Repeatedly gets tasks from queue and executes them, while coping with a number of issues:
* 主工作者运行循环。重复地从队列中获取任务并执行它们,同时处理一些问题:
* <p>
* 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.
* 我们可能从一个初始任务着手,在这种情况下我们不需要获取首个任务。否则,只要池在运行中,我们从getTask()方法中获取
* 任务。如果它返回null那么工作者由于池状态或配置参数被改变而退出。其它退出由外部代码中抛出的异常导致,在这种情况
* 下持有『突然完成』,其通常会令processWorkerExit(Worker w, boolean completedAbruptly)方法替换当前线程。
* <p>
* 2. Before running any task, the lock is acquired to prevent other pool interrupts while the task is executing, and then we
* ensure that unless pool is stopping, this thread does not have its interrupt set.
* 在运行任何任务之前,获取锁以防止在任务执行时其它池中断,然后我们确保除非池停止,否则该线程没有被设置中断。
* <p>
* 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.
* 每个任务在运行之前会调用beforeExecute(Thread t, Runnable r)方法,这个可能抛出异常,在这种情况下我们会不执行任务而
* 令线程死亡(以『突然完成』为true来打断循环)。
* <p>
* 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.
* 假设beforeExecute(Thread t, Runnable r)方法正常完成,我们运行任务,收集它抛出的任意异常发送至
* afterExecute(Runnable r, Throwable t)方法。我们单独地处理处理运行时异常,错误(这两个规格都保证我们能捕捉到)和
* 任意可抛出。因为我们不会在Runnable.run()重抛出可抛出,我们在错误的出口处包装它们(至线程的未捕捉异常处理器)。
* 任意抛出异常还会保守地导致线程死亡。
* <p>
* 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.
* 在task.run()方法完成之后,我们调用afterExecute(Runnable r, Throwable t)方法,其可能也抛出异常,其也将可能导致线程
* 死亡。根据o JLS Sec 14.20(应该是什么规范/文档),这个异常将生效,即使其是由task.run()方法抛出的。
* <p>
* 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.
* 错误机制的净效果是afterExecute(Runnable r, Throwable t)方法和未捕捉异常处理器中有我们在用户代码中遭遇的任何问题时
* 可提供的精准信息。
*
* @param w the worker 工作者
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 运行工作者
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 当新增工作者失败时将创建的新工作者进行清理,并回滚在创建新工作者时执行的操作。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法会在加主锁的情况下执行,因为【工作者集合】并不是线程安全的。加锁后,将指定工作者从【工作者集
* @Description: 合】中移除(因为工作者线程启动时可能会抛出OOM错误导致新增工作者失败,这种情况下新工作者会存在于
* @Description: 【工作者集合】中),并递减【工作者总数】,随后尝试终止当前线程池执行器。这是因为工作者会存在于【
* @Description: 工作者集合】中可能会阻碍终止,因此在将之舍弃后需要重试终止。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
final void runWorker(Worker w) {
// 方法首先会通过获取当前线程的方式获取指定工作者的工作者线程,因为runWorker(Worker w)方法只会被工作者线程自调
// 用。随后获取工作者的首个任务以备执行(如果存在的话)。在正式开始获取/执行任务之前,工作者线程会先将当前工作
// 者的【状态】由非常规初始的-1变为常规初始的0,令之可正常的运行。此时的工作者由于处于未加锁的状态,因此工作者
// 线程可能会被中断。
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
// allow interrupts
// 允许中断
// 该解锁代码的作用是令工作者的【状态】由非常规初始的-1变为常规初始的0。
w.unlock();
boolean completedAbruptly = true;
try {
// 当前工作者开始运行后,方法会进入一个死循环,循环中方法会不断的获取任务(从【任务队列】及【首个任务】中
// 获取)用于执行。当任务获取成功,工作者线程会独占前工作者,以避免自身在执行时被中断。随后判断当前线程池
// 执行器的【运行状态】是否大于等于STOP(停止),如果是,并且当前工作者线程未被中断,则需要将之中断。这是
// 因为有线程执行了shutdownNow()方法,因此理论上尚未执行的任务应该不可以再执行了。当前任务虽然实际尚未执行,
// 但由于已被工作者线程获取,无法再在shutdownNow()方法中返回,因此只能继续执行,但为了增大任务响应中断的成
// 功率(如果任务存在相关逻辑),必须在执行任务就确保工作者线程是中断状态,而不是等待并发的shutdownNow()方
// 法将之中断。
// 如果当前线程池执行器的【运行状态】是否小于STOP(停止),则要确保工作者线程未被中断。由于在获取任务的过
// 程中工作者线程处于闲置状态,因此可能会被中断。而在成功获取任务并独占工作者后(即工作者线程不再处于闲置
// 状态了),如果当前线程池执行器的【运行状态】是否小于STOP(停止),则必须取消工作者线程的中断状态,否则
// 可能导致任务的异常中断。由于期间可能存在shutdownNow()方法并发的原因,当工作者线程的中断状态被取消后,当
// 前线程池执行器的【运行状态】可能又大于等于STOP(停止)了,因此就需要重新将之再次中断(如果工作者线程还
// 没有来得及被shutdownNow()方法中断)。
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
// 如果池停止,确定线程已经中断;如果没有停止,确定线程没有中断。这需要在第二种情况中重检查以处理在清理
// 中断期间shutdownNow()方法的竞争。
if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted())
wt.interrupt();
// 任务被正式执行前,工作者线程会执行beforeExecute(Thread t, Runnable r)方法以执行前置自定义操作,随后在执
// 行任务以及后置自定义操作。如果在执行前置自定义操作期间抛出了异常,则任务不会再执行。而如果在任务执行
// 时抛出了异常(坦白说还真的不知道能抛出什么异常...理论上任务执行抛出的异常都是会被捕捉的,当然,如果指
// 定了其它类型的未来就另说,这里捕捉异常应该也是基于这种情况的考虑),则该异常会被捕捉并传递至后置自定
// 义操作中,由开发者自身决定如何处理。而无论最终任务执行是正常还是异常,都会递增【已完成任务】更新统计
// 数据,并释放对工作者的独占。
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();
}
}
// 如果任务执行异常,获取在任务完成后没有获取到新任务,则死循环会结束,即工作者不会再继续执行任务。如果是因
// 为获取不到新任务而结束,则『突然完成』会被设置为false。该参数会被传入
// processWorkerExit(Worker w, boolean completedAbruptly)方法,作为工作者退出时的影响条件。
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
// Public constructors and methods
// 公共构造器和方法
/**
* 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.
* 根据指定初始参数和默认线程工厂及拒绝执行处理器创建一个新线程池执行器。它可能更便于使用执行器集的一个工厂方法
* 代替当前常规用途构造器。
*
* @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.
* 队列用于在任务执行之前持有它们。队列将只持有通过execute()方法递交的可运行任务。
* @throws IllegalArgumentException if one of the following holds:<br>{@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br> {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* 非法参数异常:如果包含下列之一:【核心池大小】 < 0;【持续存活时间】 < 0
* 【最大池大小】 <= 0;【核心池大小】 < 【核心池大小】。
* @throws NullPointerException if {@code workQueue} is null
* 空指针异常:如果【工作队列】为null
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 线程池执行器
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建指定【核心池大小】、【最大池大小】、【持续存活时间】、【时间单位】及【工作队列】,并且【线程
* @Description: 工厂】默认为默认线程工厂,【拒绝执行处理器】默认为中断策略的执行器。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接通过调用ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
* @Description: TimeUnit unit, BlockingQueue < Runnable > workQueue, ThreadFactory threadFactory)构造方法实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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.
* 队列用于在任务执行之前持有它们。队列将只持有通过execute()方法递交的可运行任务。
* @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}
* 非法参数异常:如果包含下列之一:【核心池大小】 < 0;【持续存活时间】 < 0
* 【最大池大小】 <= 0;【核心池大小】 < 【核心池大小】。
* @throws NullPointerException if {@code workQueue} is null
* 空指针异常:如果【工作队列】为null
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 线程池执行器
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建指定【核心池大小】、【最大池大小】、【持续存活时间】、【时间单位】、【工作队列】及【线程工厂】,
* @Description: 并且【拒绝执行处理器】默认为中断策略的执行器。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接通过调用ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
* @Description: TimeUnit unit, BlockingQueue < Runnable > workQueue, ThreadFactory threadFactory)构造方法实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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.
* 队列用于在任务执行之前持有它们。队列将只持有通过execute()方法递交的可运行任务。
* @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}
* 非法参数异常:如果包含下列之一:【核心池大小】 < 0;【持续存活时间】 < 0
* 【最大池大小】 <= 0;【核心池大小】 < 【核心池大小】。
* @throws NullPointerException if {@code workQueue} is null
* 空指针异常:如果【工作队列】为null
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 线程池执行器
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建指定【核心池大小】、【最大池大小】、【持续存活时间】、【时间单位】、【工作队列】及【拒绝执行
* @Description: 处理器】,并且【线程工厂】默认为默认线程工厂的执行器。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接通过调用ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
* @Description: TimeUnit unit, BlockingQueue < Runnable > workQueue, ThreadFactory threadFactory)构造方法实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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.
* 队列用于在任务执行之前持有它们。队列将只持有通过execute()方法递交的可运行任务。
* @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}
* 非法参数异常:如果包含下列之一:【核心池大小】 < 0;【持续存活时间】 < 0
* 【最大池大小】 <= 0;【核心池大小】 < 【核心池大小】。
* @throws NullPointerException if {@code workQueue} is null
* 空指针异常:如果【工作队列】为null
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 线程池执行器
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建指定【核心池大小】、【最大池大小】、【持续存活时间】、【时间单位】、【工作队列】、【线程工厂】
* @Description: 及【拒绝执行处理器】的执行器。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接通过调用ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
* @Description: TimeUnit unit, BlockingQueue < Runnable > workQueue, ThreadFactory threadFactory)构造方法实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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.
* 在未来的某个时间执行指定任务。任务可能在一个新线程或已存在的池线程中执行。
* <p>
* 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}.
* 如果任务因为执行器已关闭或因为其容量已到达而无法递交或执行,则该任务通过当前【拒绝执行处理器】处理。
*
* @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
* 空指针:如果『命令』为null
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 执行
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 执行指定任务。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会判断当前线程池执行器的【工作者总数】是否小于【核心池大小】,如果是,则会尝试将新『命令』
* @Description: 作为『首个任务』创建新工作者以执行。如果成功则方法直接返回;否则重新获取【主池控制状态】用于后续
* @Description: 判断。
* @Description: 如果【工作者总数】大于等于【核心池大小】,或者新增新工作者失败,则判断当前线程池执行器是否处于
* @Description: RUNNING(运行中),是则说明新增工作者失败是因为【工作者总数】已触达【核心池大小】,因此尝试将『
* @Description: 命令』加入【工作队列】中。如果『命令』成功入队,则再次检查【运行状态】是否为RUNNING(运行中)。
* @Description: 如果不是则说明【运行状态】大于等于SHUTDOWN(关闭),已不允许『命令』再加入【工作队列】(但凭心
* @Description: 而论【运行状态】难道不可以是入队之后再变的么?),因此需调用remove(Runnable task)方法将『命令』移
* @Description: 除。如果成功,则调用reject(Runnable command)方法拒绝『命令』;否则说明『命令』已被工作者获取。
* @Description: 在『命令』成功入队的情况下,如果在重检查时发现【运行状态】依然是RUNNING(运行中)或移除『命令』
* @Description: 失败,则判断是否存在工作者,如果不存在则新增工作者。一般来说此处应该是存在工作者的,因为此处是核
* @Description: 心线程已满才会进入的逻辑,但确实存在无工作者的情况,例如【核心池大小】被设置为0或【允许核心线程
* @Description: 超时】被设置为true。即本身在一开始就没有创建工作者或工作者已死亡。这种情况下新入队的『命令』可能
* @Description: 永远都不会执行,因此需要新创建一个工作者以执行。
* @Description: 如果在首次检查时发现【运行状态】不为RUNNING(运行中)或者『命令』加入【工作队列】失败,则再次尝
* @Description: 试新增一个工作者。新增成功意味着当前【运行状态】为RUNNING(运行中)但【工作队列】已满,需要新增
* @Description: 工作者执行『命令』,而新增实际上也已经同步完成了;而失败则意味着【运行状态】不为RUNNING(运行中),
* @Description: 需要调用reject(Runnable command)方法拒绝『命令』。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
@Override
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
* 按3步进行
* 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.
* 如果少于【核心池大小】的线程在运行,尝试开始一个新线程并将『命令』作为它的首个任务。调用addWorker(Worker w)
* 方法原子地检查【运行状态】和【工作者总数】,从而通过返回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. 如果我们无法入队任务,那么我们尝试新增一个新线程。如果失败,我们知道我们关闭或饱满所以拒绝任务。
*/
// 方法首先会判断当前线程池执行器的【工作者总数】是否小于【核心池大小】,如果是,则会尝试将新『命令』作为『首
// 个任务』创建新工作者以执行。如果成功则方法直接返回;否则重新获取【主池控制状态】用于后续判断。
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// 如果【工作者总数】大于等于【核心池大小】,或者新增新工作者失败,则判断当前线程池执行器是否处于RUNNING(运
// 行中),是则说明新增工作者失败是因为【工作者总数】已触达【核心池大小】,因此尝试将『命令』加入【工作队列】
// 中。如果『命令』成功入队,则再次检查【运行状态】是否为RUNNING(运行中)。如果不是则说明【运行状态】大于等
// 于SHUTDOWN(关闭),已不允许『命令』再加入【工作队列】(但凭心而论【运行状态】难道不可以是入队之后再变的
// 么?),因此需调用remove(Runnable task)方法将『命令』移除。如果成功,则调用reject(Runnable command)方法拒绝『
// 命令』;否则说明『命令』已被工作者获取。
// 在『命令』成功入队的情况下,如果在重检查时发现【运行状态】依然是RUNNING(运行中)或移除『命令』失败,则判
// 断是否存在工作者,如果不存在则新增工作者。一般来说此处应该是存在工作者的,因为此处是核心线程已满才会进入的
// 逻辑,但确实存在无工作者的情况,例如【核心池大小】被设置为0或【允许核心线程超时】被设置为true。即本身在一开
// 始就没有创建工作者或工作者已死亡。这种情况下新入队的『命令』可能永远都不会执行,因此需要新创建一个工作者以
// 执行。
// 如果在首次检查时发现【运行状态】不为RUNNING(运行中)或者『命令』加入【工作队列】失败,则再次尝试新增一个
// 工作者。新增成功意味着当前【运行状态】为RUNNING(运行中)但【工作队列】已满,需要新增工作者执行『命令』,
// 而新增实际上也已经同步完成了;而失败则意味着【运行状态】不为RUNNING(运行中),需要调用
// reject(Runnable command)方法拒绝『命令』。
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.
* 该方法不会等待先前递交的任务执行完成,使用 awaitTermination(long timeout, TimeUnit unit)方法可以做到这一点。
*
* @throws SecurityException {@inheritDoc} 安全异常
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 关闭
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 关闭当前线程池执行器,关闭后当前线程池执行器会拒绝新任务递交,但不会取消旧(等待中/执行中)任务。
* @Description: 方法不会等待所有的旧任务执行完成后返回。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法在主锁的保护下首先会调用checkShutdownAccess()方法检查所有的工作者线程是否都具有"修改线程"许可,
* @Description: 这期间可能会抛出安全异常。在权限检查通过后,将当前线程池执行器的【运行状态】由RUNNING(运行中)
* @Description: 修改为SHUTDOWN(关闭)。该修改可能失败,因为可能有其它线程调用了shutdown()或shutdownNow()方法,
* @Description: 但这并不会影响后续操作。【运行状态】修改完成后,会调用interruptIdleWorkers()方法中断所有的闲置工作
* @Description: 者线程,目的是将这些工作者线程从可能陷入的等待状态中唤醒,令其可自然的死亡。随后调用onShutdown()
* @Description: 方法。onShutdown()方法是一个钩子方法,用于在当前线程池执行器关闭时执行自定义操作,其默认实现为空。
* @Description: onShutdown()方法调用后,方法会解开主锁,并调用tryTerminate()方法尝试终止当前线程池执行器。但该方法
* @Description: 未必可能成功终止当前当前线程池执行器,因为尚在工作的工作者线程及【工作队列】中的任务会阻止其终止。
* @Description: 但是这不会对最终结果造成影响,因为在每当有工作者线程死亡及【工作者队列】为空时都会调用该方法来终
* @Description: 止当前线程池执行器。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
@Override
public void shutdown() {
// 方法在主锁的保护下首先会调用checkShutdownAccess()方法检查所有的工作者线程是否都具有"修改线程"许可,这期间可
// 能会抛出安全异常。在权限检查通过后,将当前线程池执行器的【运行状态】由RUNNING(运行中)修改为SHUTDOWN(
// 关闭)。该修改可能失败,因为可能有其它线程调用了shutdown()或shutdownNow()方法,但这并不会影响后续操作。【运
// 行状态】修改完成后,会调用interruptIdleWorkers()方法中断所有的闲置工作者线程,目的是将这些工作者线程从可能陷入
// 的等待状态中唤醒,令其可自然的死亡。随后调用onShutdown()方法。onShutdown()方法是一个钩子方法,用于在当前线程
// 池执行器关闭时执行自定义操作,其默认实现为空。onShutdown()方法调用后,方法会解开主锁,并调用tryTerminate()方
// 法尝试终止当前线程池执行器。但该方法未必可能成功终止当前当前线程池执行器,因为尚在工作的工作者线程及【工作
// 队列】中的任务会阻止其终止。但是这不会对最终结果造成影响,因为在每当有工作者线程死亡及【工作者队列】为空时
// 都会调用该方法来终止当前线程池执行器。
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
// hook for ScheduledThreadPoolExecutor
// 计划线程池执行器的钩子
onShutdown();
} 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.
* 该方法不会等待积极执行中的任务终止。使用 awaitTermination(long timeout, TimeUnit unit)方法可以做到这一点。
* <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.
* 除了尽最大努力尝试停止处理正在执行的任务之外,没有任何保证。该实现通过Thread.interrupt()方法取消任务,所以任意
* 失败响应中断的任务都可能永远不会终止(就是会继续执行从而正常的完成)。
*
* @throws SecurityException {@inheritDoc} 安全异常
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 立刻关闭
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 关闭当前线程池执行器,关闭后当前线程池执行器会拒绝新任务递交,并会阻止等待中的旧任务执行,且会尝
* @Description: 试取消执行中的旧任务,最后返回未执行(等待中)的旧任务列表。方法不会等待执行中的旧任务执行取消/
* @Description: 完成后返回。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法在主锁的保护下首先会调用checkShutdownAccess()方法检查所有的工作者线程是否都具有"修改线程"许可,
* @Description: 这期间可能会抛出安全异常。在权限检查通过后,将当前线程池执行器的【运行状态】由RUNNING(运行中)
* @Description: 修改为STOP(停止)。该修改可能失败,因为可能有其它线程并发调用了shutdownNow()方法,但这并不会影
* @Description: 响后续操作。【运行状态】修改完成后,会调用interruptWorkers方法中断所有的工作者线程,一方面是取消
* @Description: 所有执行中的任务,另一方面将这些工作者线程从可能陷入的等待状态中唤醒,令其可自然的死亡。随后调用
* @Description: drainQueue方法,将所有等待中的任务迁移至一个列表中用于返回,随后解开主锁,并调用tryTerminate()方法
* @Description: 尝试终止当前线程池执行器。但该方法未必可能成功终止当前当前线程池执行器,因为尚在工作的工作者线程
* @Description: 及【工作队列】中的任务会阻止其终止。但是这不会对最终结果造成影响,因为在每当有工作者线程死亡及【
* @Description: 工作者队列】为空时都会调用该方法来终止当前线程池执行器。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
@Override
public List<Runnable> shutdownNow() {
// 方法在主锁的保护下首先会调用checkShutdownAccess()方法检查所有的工作者线程是否都具有"修改线程"许可,这期间可
// 能会抛出安全异常。在权限检查通过后,将当前线程池执行器的【运行状态】由RUNNING(运行中)修改为STOP(停止)。
// 该修改可能失败,因为可能有其它线程并发调用了shutdownNow()方法,但这并不会影响后续操作。【运行状态】修改完成
// 后,会调用interruptWorkers方法中断所有的工作者线程,一方面是取消所有执行中的任务,另一方面将这些工作者线程
// 从可能陷入的等待状态中唤醒,令其可自然的死亡。随后调用drainQueue方法,将所有等待中的任务迁移至一个列表中用
// 于返回,随后解开主锁,并调用tryTerminate()方法尝试终止当前线程池执行器。但该方法未必可能成功终止当前当前线程
// 池执行器,因为尚在工作的工作者线程及【工作队列】中的任务会阻止其终止。但是这不会对最终结果造成影响,因为在
// 每当有工作者线程死亡及【工作者队列】为空时都会调用该方法来终止当前线程池执行器。
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
@Override
public boolean isShutdown() {
return !isRunning(ctl.get());
}
/**
* Returns true if this executor is in the process of terminating after {@link #shutdown} or {@link #shutdownNow} but has
* not completely terminated. This method may be useful for debugging. A return of {@code true} reported a sufficient period
* after shutdown may indicate that submitted tasks have ignored or suppressed interruption, causing this executor not to
* properly terminate.
* 如果当前执行器在shutdown()方法和shutdownNow()方法之后正在终止但还未完全终止则返回true。该方法在调试中可能很有用。
* 关闭后返回的true上报了一个充足的周期,可能表示递交的任务已被遗忘或阻止中断,导致当前执行器无法真正终止。
*
* @return {@code true} if terminating but not yet terminated 如果正在终止但还未终止则返回true'
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 是否终止中
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 判断当前线程池执行器是否正在终止,是则返回true;否则返回false。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法会判断当前线程池执行器的【运行状态】是否大于RUNNING(运行中)且小于TERMINATED(终止),是
* @Description: 则返回true;否则返回false。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
public boolean isTerminating() {
// 方法会判断当前线程池执行器的【运行状态】是否大于RUNNING(运行中)且小于TERMINATED(终止),是则返回true;
// 否则返回false。
int c = ctl.get();
return !isRunning(c) && runStateLessThan(c, TERMINATED);
}
/**
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 是否终止
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 判断当前线程池执行器是否终止,即判断当前执行器关闭且所有旧任务都执行结束(完成/异常/取消),是则
* @Description: 返回true;否则返回false。由于关闭是终止的前提,因此该方法只会在先调用shutdown()或shutdownNow()方法
* @Description: 之后调用才有可能返回true。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法会判断当前线程池执行器的【运行状态】是否等于TERMINATED(终止),是则返回true;否则返回false。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
@Override
public boolean isTerminated() {
// 方法会判断当前线程池执行器的【运行状态】是否等于TERMINATED(终止),是则返回true;否则返回false。
return runStateAtLeast(ctl.get(), TERMINATED);
}
/**
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 等待终止
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 等待当前线程池执行器终止。如果在指定等待时间内当前线程池执行器终止则返回true;否则返回false。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法会在主锁的保护下进入一个死循环。循环中首先会判断当前线程池执行器的【运行状态】是否为
* @Description: TERMINATED(终止),如果是则直接返回true;否则继续判断当前时间是否已超出指定等待时间。如果是则
* @Description: 返回false;否则当前线程将进入等待状态,直至因为超时/信号而唤醒。唤醒后的线程将重新循环,直至因为
* @Description: 终止和超出退出为止。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
// 方法会在主锁的保护下进入一个死循环。循环中首先会判断当前线程池执行器的【运行状态】是否为TERMINATED(终止),
// 如果是则直接返回true;否则继续判断当前时间是否已超出指定等待时间。如果是则返回false;否则当前线程将进入等待
// 状态,直至因为超时/信号而唤醒。唤醒后的线程将重新循环,直至因为终止和超出退出为止。
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.
* 当当前执行器不再被引用以及它没有任何线程时调用shutdown()方法。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 终结
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 在当前线程池执行器没有外部引用且自身没有任何线程时调用,以关闭当前线程池执行器。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
@Override
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
* 空指针异常:如果『线程工厂』为null
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 设置线程工厂
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 将当前线程池执行器的【线程工厂】设置为指定线程工厂。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法通过直接设置当前线程池执行器的【线程工厂】为指定线程工厂实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @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 当前线程工厂
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取线程工厂
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器的线程工厂。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接返回当前线程池执行器的【线程工厂】实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @see #setThreadFactory(ThreadFactory)
*/
public ThreadFactory getThreadFactory() {
return threadFactory;
}
/**
* Sets a new handler for unexecutable tasks.
* 为无法执行的任务设置一个新处理器
*
* @param handler the new handler 新处理器
* @throws NullPointerException if handler is null
* 空指针异常:如果处理器为null
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 设置拒绝执行处理器
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 将当前线程池执行器的【处理器】设置为指定拒绝执行处理器。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法通过直接设置当前线程池执行器的【处理器】为指定拒绝执行处理器实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @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 当前处理器
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取拒绝执行处理器
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器的拒绝执行处理器。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接返回当前线程池执行器的【处理器】。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @see #setRejectedExecutionHandler(RejectedExecutionHandler)
*/
public RejectedExecutionHandler getRejectedExecutionHandler() {
return handler;
}
/**
* Sets the core 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. If larger, new threads will, if needed,
* be started to execute any queued tasks.
* 设置核心线程的数量。这会重写在构造方法中设置的任何值。如果新值比当前值小,额外的线程将在下次闲置时终结。如果更大,
* 如果需要,新线程将于指定任意已入队的任务时开始。
*
* @param corePoolSize the new core size 新核心大小
* @throws IllegalArgumentException if {@code corePoolSize < 0}
* 非法参数异常:如果『核心池大小』小于0
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 设置核心池大小
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 设置当前线程池执行器的核心池大小。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会判断『核心池大小』是否合法,否则抛出非法参数异常。计算『核心池大小』与【核心池大小】的
* @Description: 差值,随后判断当前【工作者总数】是否大于核心池大小,是则调用interruptIdleWorkers()方法中断所有的闲
* @Description: 置工作者;否则判断差值是否大于0。是则意味着『核心池大小』大于【核心池大小】,需要相应的创建更多
* @Description: 工作者来执行任务。
* @Description: 方法会选择创建差值与【工作队列】大小中的较小值数量的工作者,这样就既不会使【工作者总数】大于【核
* @Description: 心池大小】,又不会导致【工作者总数】大于当前【工作队列】中任务的数量。创建工作者的操作是通过循环
* @Description: 实现的,如果工作者创建成功,并且新增的【工作者总数】没有达到差值,则会不断的创建下去,直至达到指
* @Description: 定数量。但如果在过程中创建工作者失败或【工作队列】变为空,则循环就会终止,因为这意味着【工作总数】
* @Description: 已触达【核心池大小】或已没有任务需要执行,无需在创建新的工作者了。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @see #getCorePoolSize
*/
public void setCorePoolSize(int corePoolSize) {
// 方法首先会判断『核心池大小』是否合法,否则抛出非法参数异常。计算『核心池大小』与【核心池大小】的差值,随后
// 判断当前【工作者总数】是否大于核心池大小,是则调用interruptIdleWorkers()方法中断所有的闲置工作者;否则判断差
// 值是否大于0。是则意味着『核心池大小』大于【核心池大小】,需要相应的创建更多工作者来执行任务。
// 方法会选择创建差值与【工作队列】大小中的较小值数量的工作者,这样就既不会使【工作者总数】大于【核心池大小】,
// 又不会导致【工作者总数】大于当前【工作队列】中任务的数量。创建工作者的操作是通过循环实现的,如果工作者创建
// 成功,并且新增的【工作者总数】没有达到差值,则会不断的创建下去,直至达到指定数量。但如果在过程中创建工作者
// 失败或【工作队列】变为空,则循环就会终止,因为这意味着【工作总数】已触达【核心池大小】或已没有任务需要执行,
// 无需在创建新的工作者了。
if (corePoolSize < 0)
throw new IllegalArgumentException();
int delta = corePoolSize - this.corePoolSize;
this.corePoolSize = corePoolSize;
if (workerCountOf(ctl.get()) > corePoolSize)
interruptIdleWorkers();
else if (delta > 0) {
// We don't really know how many new threads are "needed". As a heuristic, prestart enough new workers (up to new
// core size) to handle the current number of tasks in queue, but stop if queue becomes empty while doing so.
//我们并不真正的知道需要多少新线程。作为一个启发式方法,预先启动足够数量的新工作者(相当于新核心大小)来处
// 理队列中的当前数量,但如果队列在操作期间变为空则停止。
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 线程的核心数量
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取核心池大小
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器的核心池大小。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接通过返回【核心池大小】实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @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.
* 开始一个核心线程,使之空闲的等待任务。该将覆盖只当新任务已执行时才启动核心线程的默认策略。如果所有核心线程已经
* 启动该方法将返回false。
*
* @return {@code true} if a thread was started 如果开始一个线程则返回true
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 预启动核心线程
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建一个核心线程以等待任务,创建成功则返回true;否则返回false。失败是因为核心线程数量已达到上限。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会判断当前【工作者总数】是否小于【核心池大小】,否则直接返回false,因此已经无法再新增核心
* @Description: 工作者了;是则创建新工作者,并返回最终创建成果。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
public boolean prestartCoreThread() {
// 方法首先会判断当前【工作者总数】是否小于【核心池大小】,否则直接返回false,因此已经无法再新增核心工作者了;
// 是则创建新工作者,并返回最终创建成果。
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()方法一致,除了即使核心池大小为0也会安排启动至少一个线程之外。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 预启动核心线程
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建一个核心线程以等待任务,如果当前线程池执行器未安排创建核心线程,则创建一个非核心线程以等待
* @Description: 任务。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会判断当前【工作者总数】是否小于【核心池大小】,是则直接创建一个新工作者,并且无视其创建
* @Description: 结果;否则继续判断【工作者总数】是否为0。是则说明【核心池大小】为0,即当前线程池执行器不安排创建
* @Description: 核心线程,这种情况下安排其创建一个非核心线程,同样不考虑其创建结果。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
void ensurePrestart() {
// 方法首先会判断当前【工作者总数】是否小于【核心池大小】,是则直接创建一个新工作者,并且无视其创建结果;否则
// 继续判断【工作者总数】是否为0。是则说明【核心池大小】为0,即当前线程池执行器不安排创建核心线程,这种情况下
// 安排其创建一个非核心线程,同样不考虑其创建结果。
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 线程启动的数量
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 预启动所有核心线程
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建所有核心线程以等待任务,并返回成功创建的核心线程数量。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法会循环的不断创建核心工作者,每次成功创建都会递增创建总数,直至失败为止。失败后将创建总数返回。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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.
* 如果当前池允许核心线程超时并且如果没有任务在持续存活时间内到达时终止则返回true,当新任务到达时将被替换。当为true
* 时,应用于非核心线程的持续存活策略将同样应用于核心线程。当为false(默认),核心线程永远不会由于缺乏到来的任务而
* 终止。
*
* @return {@code true} if core threads are allowed to time out, else {@code false}
* 如果核心线程允许超时则返回true;否则返回false。
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 允许核心线程超时
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 判断当前线程池执行器是否允许核心线程因为超时而死亡,是则返回true;否则返回false。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接返回【允许核心线程超时】实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @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时,应用于非核心线程的持续存活策略将同样引用与核心
* 线程。为了避免多次重复的线程替换/保留,持续存活时间在设置为true时必须大于0。该方法通常应该在池被积极使用之前
* 调用。
*
* @param value {@code true} if should time out, else {@code false} 如果应该超时则为true;否则为false。
* @throws IllegalArgumentException if value is {@code true} and the current keep-alive time is not greater than zero
* 非法参数异常:如果只为true并且当前持续存活时间不大于0
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 允许核心线程超时
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 设置当前线程池执行器的核心线程是否允许因为超时而死亡。当设置为true时,当前线程池执行器的持续存活
* @Description: 必须大于0,否则会抛出非法参数异常。因为为0时有很大概率会导致核心线程频繁的复活,即在死亡之前重新
* @Description: 用于执行任务。复活可以充分的利用已创建的线程,但同样也是一项对性能有影响的操作。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接返回【允许核心线程超时】实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @since 1.6
*/
public void allowCoreThreadTimeOut(boolean value) {
// 方法首先会判断『值』是否为true且【持续存活时间】小于等于0,是则直接抛出非法参数异常。因为这将大概率的导致核
// 心线程频繁的复活,导致较为严重的性能损耗。而非核心线程由于创建的条件较为苛刻,因此导致复活的概率相对较低。
if (value && keepAliveTime <= 0)
throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
// 随后将【持续存活时间】赋值为『值』,并如果『值』为true,则重点所有的闲置线程,目的是令唤醒等待中的核心线程并
// 令之死亡。
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}
* 非法参数异常:如果新最大值小于或等于0,或小于核心池大小
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 设置最大池大小
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 设置当前线程池执行器的最大池大小。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会判断『最大池大小』是否合法,不合法则抛出非法参数异常。随后将【最大池大小】赋值为『最大
* @Description: 池大小』,并判断【工作者总数】是否大于【最大池大小】,是中断所有的闲置工作者线程,目的是将之从可
* @Description: 能得等待状态中唤醒并令之死亡。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @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 所允许的线程最大值
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取最大池大小
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器的最大池大小。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接返回【最大池线程】实现
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @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.
* 等待时间,0将导致额外线程在执行任务之后直接终止。
* @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}
* 如果时间小于0或(等于0并且允许核心线程超时)
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取持续存活时间
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器的持续存活时间。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会判断『时间』是否小于0,是则直接抛出非法参数异常。随后判断『时间』是否等于0且【允许核心
* @Description: 线程超时】为true。是则同样直接抛出非法参数异常。因为这将大概率导致核心线程频繁的复活而造成严重的
* @Description: 性能损失。
* @Description: 合法性判断之后将『时间』通过『单位』转换为『纳秒时间』,并计算『纳秒时间』与【持续存活时间】的『
* @Description: 差值』,用于作为稍后的中断操作的判断条件。随后将【持续存活时间】赋值为『纳秒时间』,判断『差值』
* @Description: 是否小于0。是则说明『纳秒时间』小于原来的【持续存活时间】,因此当前等待中的工作者线程可能已经超
* @Description: 时,因此需要通过中断所有的闲置工作者线程,将之唤醒并令之重新等待。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @see #getKeepAliveTime(TimeUnit)
*/
public void setKeepAliveTime(long time, TimeUnit unit) {
// 方法首先会判断『时间』是否小于0,是则直接抛出非法参数异常。随后判断『时间』是否等于0且【允许核心线程超时】
// 为true。是则同样直接抛出非法参数异常。因为这将大概率导致核心线程频繁的复活而造成严重的性能损失。
// 合法性判断之后将『时间』通过『单位』转换为『纳秒时间』,并计算『纳秒时间』与【持续存活时间】的『差值』,用
// 于作为稍后的中断操作的判断条件。随后将【持续存活时间】赋值为『纳秒时间』,判断『差值』是否小于0。是则说明
// 『纳秒时间』小于原来的【持续存活时间】,因此当前等待中的工作者线程可能已经超时,因此需要通过中断所有的闲置
// 工作者线程,将之唤醒并令之重新等待。
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 时间限制
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取持续存活时间
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器的持续存活时间。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法会将【持续存活时间】转换为指定单位时间后返回。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
* @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 任务队列
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取队列
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器的任务队列。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法会直接将【任务队列】返回。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
public BlockingQueue<Runnable> getQueue() {
return workQueue;
}
/**
* Removes this task from the executor's internal queue if it is present, thus causing it not to be run if it has not already
* started.
* 如果存在,从执行器的内部队列中移除任务,如果它还未开始则会导致它不在运行。
* <p>
* This method may be useful as one part of a cancellation scheme. It may fail to remove tasks that have been converted
* into other forms before being placed on the internal queue. For example, a task entered using {@code submit} might be
* converted into a form that maintains {@code Future} status. However, in such cases, method {@link #purge} may be used
* to remove those Futures that have been cancelled.
* 该方法可能用于作为取消计划的一部分。它可能因为放置在内部队列之前被转变为其它格式而移除任务失败。例如,一个任务
* 使用submit()方法进入可能转变为维持未来状态的格式。此外,在如此情况下,purge()方法可能用于移除已取消的任务。
*
* @param task the task to remove 用于移除的任务
* @return {@code true} if the task was removed 如果移除则返回true
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 移除
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 将指定任务从当前线程池执行器的任务队列中移除,成功返回true;否则返回false。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法通过【工作队列】的remove()方法将指定任务移除,并返回移除的结果。由于【工作队列】中的任务会妨
* @Description: 碍shutdown()方法导致的终止,因此无论移除的结果如何,都需要尝试将当前线程池执行器终止,最后返回移
* @Description: 除结果。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
public boolean remove(Runnable task) {
// 方法通过【工作队列】的remove()方法将指定任务移除,并返回移除的结果。由于【工作队列】中的任务会妨碍shutdown()
// 方法导致的终止,因此无论移除的结果如何,都需要尝试将当前线程池执行器终止,最后返回移除结果。
boolean removed = workQueue.remove(task);
// In case SHUTDOWN and now empty
// 在关闭和不为空的情况下
tryTerminate();
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.
* 尝试从工作队列中移除所有已被取消的未来任务。该方法作为一个存储空间回收操作很有用,对功能没有其它影响。已取消
* 的任务永远不会执行,但可能在工作队列中累积直到工作者线程可以积极的移除它们。调用该方法代替尝试实时的移除它们。
* 此外,该方法在面对其它线程的干扰时可能失败移除任务。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 清洗
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 从当前线程池执行器的任务队列中将所有已取消的未来任务移除。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法会获取【工作队列】的迭代器,随后不断迭代,将所有已取消的任务从【工作队列】中移除。该过程中可
* @Description: 能会抛出并发修改异常,这说明【工作队列】的迭代器使用了快速失败机制实现。此时会采取遍历拷贝的方式
* @Description: 加调用内部移除方法的方式移除。该移除不会受并发的影响,但可能会减低清洗的执行效率。因为如果【工作
* @Description: 队列】是基于链表实现的,则清洗的时间复杂度会由O(N)变为O(N*N)。因为在链表中查询执行元素是需要遍历
* @Description: 的。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
public void purge() {
// 方法会获取【工作队列】的迭代器,随后不断迭代,将所有已取消的任务从【工作队列】中移除。该过程中可能会抛出并
// 发修改异常,这说明【工作队列】的迭代器使用了快速失败机制实现。此时会采取遍历拷贝的方式加调用内部移除方法的
// 方式移除。该移除不会受并发的影响,但可能会减低清洗的执行效率。因为如果【工作队列】是基于链表实现的,则清洗
// 的时间复杂度会由O(N)变为O(N*N)。因为在链表中查询执行元素是需要遍历的。
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).
// 如果在遍历期间我们遭遇干扰则走慢路。遍历拷贝并调用移除已取消的节点。该慢路更可能是O(N*N)。
for (Object r : q.toArray())
if (r instanceof Future<?> && ((Future<?>) r).isCancelled())
q.remove(r);
}
// In case SHUTDOWN and now empty
// 在SHUTDOWN(关闭)及不为空的情况下。
tryTerminate();
}
/* Statistics */
/**
* Returns the current number of threads in the pool.
* 返回池中线程的当前数量。
*
* @return the number of threads 线程数量
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取池大小
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器的实际线程总数。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会加主锁,随后在主锁的保护下判断【运行状态】是否大于等于TIDYING(整理中),是则说当前线
* @Description: 程池执行器中已没有存活的工作者线程,直接返回0;否则返回【工作者集合】的大小。为什么不返回【工作
* @Description: 者总数】呢?这是因为【工作者总数】是理论数量,而【工作者集合】的大小则是实际数量。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
public int getPoolSize() {
// 方法首先会加主锁,随后在主锁的保护下判断【运行状态】是否大于等于TIDYING(整理中),是则说当前线程池执行器
// 中已没有存活的工作者线程,直接返回0;否则返回【工作者集合】的大小。为什么不返回【工作者总数】呢?这是因为
// 【工作者总数】是理论数量,而【工作者集合】的大小则是实际数量。
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Remove rare and surprising possibility of isTerminated() && getPoolSize() > 0
// 移除很少和令人惊讶的可能性terminate () && 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 线程数量
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取活跃总数
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器中正在执行任务的线程的近似数量。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会加主锁,以防止其它线程的外部干扰。随后在主锁的保护下遍历【工作者集合】,判断每个工作者
* @Description: 是否被独占。是则说明该工作者中的工作者线程正在执行任务,计数递增。当整个遍历完成后,返回计数。
* @Description: 由于在此过程中,可能有新工作者线程参与退出执行任务,因此该方法只能获取到近似的活跃线程数量。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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 线程数量
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取最大规模池大小
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器中曾经同时最多存在的线程的数量。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法在主锁的保护下直接返回【最大规模池大小】实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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 任务数量
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取任务总数
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器执行中/已执行任务总数的近似值。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法在主锁的保护下获取当前线程池执行器的【已完成任务总数】,随后遍历【工作者集合】,将每个工作者
* @Description: 的【已完成任务】添加,以计算最终的执行中/已执行任务总数的近似值。并且如果通过独占判断到当前工作
* @Description: 者正在执行任务,则还会将执行中/已执行任务总数递增,因此该任务已被计划执行。
* @Description: 之所以是近似值是因为在当前方法的执行期间可能有新任务被完成或开始执行,但可能已无法再增加至已执行
* @Description: 任务总数中了。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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 任务的数量
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 获取已完成任务总数
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 获取当前线程池执行器已执行任务总数的近似值。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法在主锁的保护下获取当前线程池执行器的【已完成任务总数】,随后遍历【工作者集合】,将每个工作者
* @Description: 的【已完成任务】添加,以计算最终的已执行任务总数的近似值。
* @Description: 之所以是近似值是因为在当前方法的执行期间可能有新任务被完成或开始执行,但可能已无法再增加至已执行
* @Description: 任务总数中了。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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
*/
@Override
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.
* 方法在指定线程中优先于指定可运行执行调用。该方法将被执行任务r的线程调用,并且可能重初始化线程本地,或执行日志。
* <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 将要执行的任务
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 执行之前
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 在指定任务被指定线程执行之前执行自定义操作
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法什么也不做。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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.
* 方法在指定可运行执行完成后调用。该方法由已执行任务的线程调用。如果不为null,则可抛出为导致执行突然中断的未捕捉
* 运行时异常或错误。
* <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.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:
* 注意:当活动被显示或通过如submit()方法被关在了如未来任务的任务里,这些任务对象捕捉并维护计算的异常,所以异常不会
* 导致突然终止,并且内部异常不会传递至当前方法(即如果任务是实际是在未来任务等对象中运行的,则执行过程中的异常会
* 被捕捉,不会传递到该方法中)。如果你期望在当前方法中捕捉失败的两种类型,你可以进一步研究如此情况,就像这示例的
* 子类一样,如果一个任务已被中断,要么直接打印原因,要么打印底层:
* <pre> {@code
* class ExtendedExecutor extends ThreadPoolExecutor {
* // ...
* protected void afterExecute(Runnable r, Throwable t) {
* // 调用父类的afterExecute(Runnable r, Throwable t)方法。
* super.afterExecute(r, t);
* // 如果任务是以未来的形式执行的,则便从未来中获取执行结果,如果是异常,则会被get()方法抛出。
* 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
* 导致终止的异常,或者如果执行正常地完成则为null
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 执行之后
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 在指定任务被执行之后执行自定义操作,该方法会传入执行过程中抛出的异常。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法什么也不做。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
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.
* 方法在执行器已终止时调用该。默认实现什么也不做。注意:为了合理地嵌套多重写,子类通常应该在方法中调用
* super.terminated()
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 已终止
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 在当前线程池迭代器被终止时执行自定义逻辑。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
protected void terminated() {
}
/* Predefined RejectedExecutionHandlers */
/* 预定义的拒绝执行处理器 */
/**
* A handler for rejected tasks that runs the rejected task directly in the calling thread of the {@code execute} method,
* unless the executor has been shut down, in which case the task is discarded.
* 一个被拒绝任务的处理器,在execute()方法的调用线程中直接执行被拒绝的任务,除非执行器已经关闭,在这种情况下任务
* 将被抛弃。
*/
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
* 创建调用者运行策略。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 调用者运行策略
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建调用者运行策略。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
public CallerRunsPolicy() {
}
/**
* Executes task r in the caller's thread, unless the executor has been shut down, in which case the task is discarded.
* 在调用者的线程中执行任务r,除非执行器已经关闭,在这种情况下任务将被抛弃。
*
* @param r the runnable task requested to be executed 用于请求执行的可运行任务
* @param e the executor attempting to execute this task 执行器尝试执行该任务
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 拒绝执行
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 在当前线程池执行器未关闭的情况下,使用当前线程执行任务。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会判断当前线程池执行器是否关闭,否则执行执行可运行任务。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 方法首先会判断当前线程池执行器是否关闭,否则执行执行可运行任务。
if (!e.isShutdown()) {
r.run();
}
}
}
/**
* A handler for rejected tasks that throws a {@code RejectedExecutionException}.
* 一个抛出拒绝执行异常的被拒绝任务处理器,
*/
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
* 创建中止策略
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 中止策略
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建中止策略。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
public AbortPolicy() {
}
/**
* Always throws RejectedExecutionException.
* 总是抛出拒绝执行异常。
*
* @param r the runnable task requested to be executed 用于请求执行的可运行任务
* @param e the executor attempting to execute this task 执行器尝试执行该任务
* @throws RejectedExecutionException always
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 拒绝执行
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 抛出拒绝执行异常处理拒绝任务。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法直接抛出拒绝执行异常实现。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
/**
* A handler for rejected tasks that silently discards the rejected task.
* 一个安静求其已拒绝任务的拒绝任务处理器。
*/
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
* 创建丢弃策略
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 丢弃策略
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建丢弃策略。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
public DiscardPolicy() {
}
/**
* Does nothing, which has the effect of discarding task r.
* 什么也不做,有丢弃任务r的效果。
*
* @param r the runnable task requested to be executed 用于请求执行的可运行任务
* @param e the executor attempting to execute this task 执行器尝试执行该任务
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 拒绝执行
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 抛弃已拒绝任务。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法什么也不做。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
/**
* A handler for rejected tasks that discards the oldest unhandled request and then retries {@code execute}, unless the executor
* is shut down, in which case the task is discarded.
* 丢弃最老请求并尝试执行的拒绝任务处理器,除非执行器被关闭,这种情况下任务将被抛弃。
*/
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
* 创建指定执行器的丢弃最老策略。
*
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 丢弃最老策略
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 创建丢弃最老策略。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
public DiscardOldestPolicy() {
}
/**
* Obtains and ignores the next task that the executor would otherwise execute, if one is immediately available, and then
* retries execution of task r, unless the executor is shut down, in which case task r is instead discarded.
* 获取并忽略执行器将立即执行的下一个任务,然后重试任务r的执行,除非执行器被关闭,在这种情况下,任务r被丢弃。
*
* @param r the runnable task requested to be executed 用于请求执行的可运行任务
* @param e the executor attempting to execute this task 执行器尝试执行该任务
* @Description: --------------------------------------------------------------- 名称 ---------------------------------------------------------------
* @Description: 拒绝执行
* @Description: --------------------------------------------------------------- 作用 ---------------------------------------------------------------
* @Description: 在指定线程池执行器未关闭的情况下丢弃其任务队列中最老的任务并执行指定任务。
* @Description: --------------------------------------------------------------- 逻辑 ---------------------------------------------------------------
* @Description: 方法首先会判断执行线程池执行器是否关闭,否则抛弃任务队列中最老的任务,随后执行指定任务。
* @Description: --------------------------------------------------------------- 注意 ---------------------------------------------------------------
* @Description: ~
* @Description: --------------------------------------------------------------- 疑问 ---------------------------------------------------------------
* @Description: ~
*/
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 方法首先会判断执行线程池执行器是否关闭,否则抛弃任务队列中最老的任务,随后执行指定任务。
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
}