ThreadPoolExecutor ---》AbstractExecutorService-->ExecutorService-->Executor
/**
//使用池化的线程
* 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//1)无限数量线程池 (能自动螺旋回收)
* 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:
*
* <dl>
------------------------------
//1)核心和最大线程池数量
* <dt>Core and maximum pool sizes</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}).//当一个新的任务提交到execute方法时,
//1--运行的线程数小于corePoolSize核心线程数,新的线程会被创建
* 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.//2--当大于核心,小于max的时候,queue队列也满了,会创建新线程,
If there are more than corePoolSize but less than
* maximumPoolSize threads running, a new thread will be created only
* if the queue is full.//corePoolSize==maximumPoolSize,,固定大小的线程池
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.//一般来说,core and maximum pool sizes 通过构造设置,但也可以用set方法
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>
*//按需建设
* <dt>On-demand construction</dt>
//即使是核心线程数,也是在新任务到达的时候创建
* <dd>By default, even core threads are initially created and
* started only when new tasks arrive,//预先开启核心线程数 prestartCoreThread (1个)或者 prestartAllCoreThreads(全部)
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. </dd>
------------------------------
//2)创建新线程
* <dt>Creating new threads</dt>//使用 ThreadFactory 创建新线程
* <dd>New threads are created using a {@link ThreadFactory}.
//如果没有特别指定,使用Executors#defaultThreadFactory创建线程
//1-相同的ThreadGroup线程组
//2-相同的优先级 NORM_PRIORITY
//3-非守护进程 non-daemon
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.//通过提供不同的线程工厂,可以修改 thread's name, thread group, priority, daemon status)等信息
By supplying a different ThreadFactory, you can
* alter the thread's name, thread group, priority, daemon status,
* etc.//如果线程工厂创建线程失败时(newThread),执行器会继续,但是不能执行任务
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.</dd>
*------------------------------
//3)线程存活时间
* <dt>Keep-alive times</dt>
//多余核心线程数的线程,会被终止
* <dd>If the pool currently has more than corePoolSize threads,
* excess threads will be terminated//空闲超过keepAliveTime 时间后
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.//这个参数可以动态调整setKeepAliveTime
This parameter can also be changed dynamically using method {@link #setKeepAliveTime(long, TimeUnit)}.
//使用Long的最大值,纳秒可以
Using a value of {@code Long.MAX_VALUE} {@link
* TimeUnit#NANOSECONDS} effectively disables idle threads from ever
* terminating prior to shut down.//默认keep-alive 策略,只对超过核心线程数的线程有效果
By default, the keep-alive policy
* applies only when there are more than corePoolSize threads.//但是,allowCoreThreadTimeOut 这个方法可以调整,对核心线程数楪祈效果,只要keepAliveTime非0
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. </dd>------------------------------
//4)队列
* <dt>Queuing</dt>
//任意的阻塞队列BlockingQueue ,可能被使用来传递和保存提交的任务
* <dd>Any {@link BlockingQueue} may be used to transfer and hold
* submitted tasks.
//使用这个队列和池的大小互相影响
The use of this queue interacts with pool sizing:
*
* <ul>
// 1.正在运行线程小于核心线程数,执行器总更喜欢创建新的线程
* <li> If fewer than corePoolSize threads are running, the Executor
* always prefers adding a new thread
* rather than queuing.</li>// 2.如果核心线程数或者更多线程在运行,执行器更喜欢将任务入队,而不是创建新线程
* <li> If corePoolSize or more threads are running, the Executor
* always prefers queuing a request rather than adding a new
* thread.</li>//3.如果任务无法入队,只要不超过最大线程数,就会创建新线程处理
//否则,任务会被拒绝
* <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>
*//3种入队策略
* There are three general strategies for queuing:
* <ol>
//1.直接传递
* <li> <em> Direct handoffs.</em>
//一个好的,默认选择是同步队列 SynchronousQueue,直接给线程而不是用队列保存
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.
//直接处理,通常需要无界的maximumPoolSizes,避免因为没有可用线程导致拒绝
* 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>//2.无界队列
* <li><em> Unbounded queues.</em>
//使用无界阻塞队列LinkedBlockingQueue,导致所有的新任务等待在队列中,当所有核心线程都busy的时候
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.//因此,不会与超过corePoolSize的线程被创建
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>//3.有界队列
* <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:
//大队列,小池
1)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.//小队列,大池
2)Use of small queues generally requires larger pool sizes,
which keeps CPUs busier but may encounter unacceptable scheduling overhead,
which also decreases throughput.
</li>
* </ol>
*
* </dd>------------------------------
//5)拒绝的任务
* <dt>Rejected tasks</dt>
//一个新的任务被提交进 #execute(Runnable) 方法时,可能会被拒绝
* <dd>New tasks submitted in method {@link #execute(Runnable)} will be <em>rejected</em>
//当执行器被关闭或者最大线程数和任务队列有容量且饱和的时候
when the Executor has been shut down,
and also whenthe 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}.//4种预定义的处理策略提供如下
Four predefined handler policies are provided:
*
* <ol>
//1.中止策略,抛出RejectedExecutionException
* <li> In the default {@link ThreadPoolExecutor.AbortPolicy}, the
* handler throws a runtime {@link RejectedExecutionException} upon
* rejection. </li>
//2.调用者运行策略,可能降低任务提交的速率
* <li> In {@link ThreadPoolExecutor.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. </li>
//3.抛弃策略,简单丢弃
* <li> In {@link ThreadPoolExecutor.DiscardPolicy}, a task that
* cannot be executed is simply dropped. </li>
//4.丢弃最老策略 ,丢弃任务队列中最前面的任务,如果失败,重复这个步骤
* <li>In {@link ThreadPoolExecutor.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>
*
* 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>//6)关闭钩子方法
* <dt>Hook methods</dt>
//每个任务执行的前后,执行这些钩子方法 beforeExecute + afterExecute
* <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 tomanipulate the execution environment;
//如,重新初始化线程本地变量,统计,添加日志记录
for example, reinitializing ThreadLocals, gathering statistics, or adding log entries.//另外,方法terminated可执行任何操作,当执行器被完全关闭的时候
Additionally, method {@link #terminated} can be overridden to perform
* any special processing that needs to be done once the Executor has
* fully terminated.
//如果钩子或者回调方法抛出异常,则内部工作线程会失败或者童然终止
* <p>If hook or callback methods throw exceptions, internal worker
* threads may in turn fail and abruptly terminate.</dd>
//队列维护
* <dt>Queue maintenance</dt>
//使用getQueue方法,访问工作队列,进行监控和调试
* <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.</dd>
*//终止,结束
* <dt>Finalization</dt>
//用户没有主动调用shutdown的时候
* <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)}. </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) {
* super.beforeExecute(t, r);
* pauseLock.lock();
* try {
* 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>
*
* @since 1.5
* @author Doug Lea
*/