Java通过Executors提供四种线程池,分别为:
/**
* 使用给定的初始参数创建新ThreadPoolExecutor
*
* @param corePoolSize 保留在池中的线程数,即使它们是空闲的,除非设置了allowCoreThreadTimeOut
* @param maximumPoolSize 池中允许的最大线程数
* @param keepAliveTime 当线程数量大于核心时,这是多余空闲线程在终止前等待新任务的最大时间。
* @param unit keepAliveTime参数的时间单位
* @param workQueue 在执行任务之前用于保存任务的队列。此队列将只保存由execute方法提交的可运行任务。
* @param threadFactory 执行器创建新线程时使用的工厂
* 默认为DefaultThreadFactory, Thread newThread(Runnable r) 创建新的线程。
* @param handler 当执行被阻塞时使用的处理程序,因为线程边界和队列容量已经达到
默认 AbortPolicy 总是抛出rejectedExecution。
* @throws IllegalArgumentException 以下任意条件满足,抛出IllegalArgumentException
* corePoolSize < 0
* keepAliveTime < 0
* maximumPoolSize <= 0
* maximumPoolSize < corePoolSize
* @throws NullPointerException 如果 workQueue or threadFactory or handler is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.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;
}
@Slf4j
public class ThreadPoolExample {
public static void main(String[] args) {
ArrayBlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(6);
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 3000, TimeUnit.MILLISECONDS, blockingQueue, new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
log.info("执行拒绝策略: corePoolSize :{},maxPoolSize:{},queue size : {} ", executor.getCorePoolSize(), executor.getMaximumPoolSize(), executor.getQueue().size());
}
});
AtomicInteger atomicInteger = new AtomicInteger();
for (int i = 0; i < 20; i++) {
executor.execute(() -> {
System.out.println(executor.getCorePoolSize() + "-" + executor.getPoolSize() + "-" + executor.getQueue().size());
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
}
打印输出:
5-2-0
5-2-0
5-4-0
5-5-0
5-5-1
5-6-6
5-8-6
5-9-6
5-9-6
5-10-6
5-10-5
5-10-3
5-10-4
5-10-2
5-10-1
5-10-0
执行拒绝策略: corePoolSize :5,maxPoolSize:10,queue size : 6
5-10-1
5-10-0
5-10-1
public void execute(Runnable command) {
//需要执行的任务command为空,抛出空指针异常
if (command == null)
throw new NullPointerException();
/*
*执行的流程实际上分为三步
*1、如果运行的线程小于corePoolSize,以用户给定的Runable对象新开一个线程去执行
* 并且执行addWorker方法会以原子性操作去检查runState和workerCount,以防止当返回false的
* 时候添加了不应该添加的线程
*2、 如果任务能够成功添加到队列当中,我们仍需要对添加的线程进行双重检查,有可能添加的线程在前
* 一次检查时已经死亡,又或者在进入该方法的时候线程池关闭了。所以我们需要复查状态,并有有必
* 要的话需要在停止时回滚入列操作,或者在没有线程的时候新开一个线程
*3、如果任务无法入列,那我们需要尝试新增一个线程,如果新建线程失败了,我们就知道线程可能关闭了
* 或者饱和了,就需要拒绝这个任务
*
*/
//获取线程池的状态
int c = ctl.get();
//工作线程 < corePoolSize
if (workerCountOf(c) < corePoolSize) {
//处于运行状态的线程数小于核心线程数,添加任务到worker集合当中
//添加核心任务,如果成功,方法结束
if (addWorker(command, true))
//成功返回
return;
//失败的话再次获取线程池的状态
c = ctl.get();
}
//工作线程 >= corePoolSize 时,如果线程池处于运行状态,将任务加入到阻塞队列中
if (isRunning(c) && workQueue.offer(command)) {
//再次获取线程池的状态
int recheck = ctl.get();
//再次检查状态
//如果线程池不处于RUNNING状态,将任务从workQueue队列中移除,并且拒绝任务
if (! isRunning(recheck) && remove(command))
reject(command);
//如果线程池处于RUNNING,此时线程池的工作线程个数为0,加入新的非核心任务
else if (workerCountOf(recheck) == 0)
//添加非核心的worker 为null 此处目的:避免堵塞队列的任务没有工作线程去执行。
addWorker(null, false);
}
//队列添加失败的话(满了),就添加到非核心任务
else if (!addWorker(command, false))
//添加到非核心任务失败,可能是大于最大线程数导致
reject(command);
}
final void reject(Runnable command) {
handler.rejectedExecution(command, this);
}
就是调用handler.rejectedExecution(command, this); 由具体的拒绝策略实现。
private boolean addWorker(Runnable firstTask, boolean core) {
//外部循环标记
retry:
//外层死循环
for (;;) {
//获取线程池控制状态
int c = ctl.get();
//获取 线程池的运行状态
int rs = runStateOf(c);
/**
* 1. 状态为SHUTDOWN,进来的任务为空,但堵塞队列不是空 这种情况下,还是要继续执行的
* 2. 线程池runState至少已经是SHUTDOWN,且不满足条件1,直接返回false
*/
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
//内层死循环
for (;;) {
//获取线程池的线程个数
int wc = workerCountOf(c);
// 如果是核心的 线程个数大于核心数就不添加
//如果非核心,线程个数大于最大线程池数量就不添加
//返回false
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//增加workerCount +1 (原子操作)
if (compareAndIncrementWorkerCount(c))
// 如果增加成功,跳出循环,进行下面的创建Worker执行任务
break retry;
c = ctl.get(); // 失败重新获取线程池ctl
// 判断当前runState与最开始rs是否相等,不相等说明状态已经被修改,返回重新执行
if (runStateOf(c) != rs)
continue retry;
}
}
//标志 工作线程是否已开始
boolean workerStarted = false;
//标志 工作线程新建是否已完成
boolean workerAdded = false;
Worker w = null;
try {
// 根据firstTask创建Worker开始执行任务
w = new Worker(firstTask);
//注意: thread 和 firstTask是不同的,thread是threadFatory new出来的
final Thread t = w.thread;
if (t != null) {
// 使用重入锁的目的是因为workers使用的是 HashSet线程不安全
final ReentrantLock mainLock = this.mainLock;
// 加锁
mainLock.lock();
try {
//持有锁时重新检查。在ThreadFactory失败或获取锁之前关闭时退出。
int rs = runStateOf(ctl.get());
//如果线程池状态为RUNNING,或者(线程状态为SHUTDOWN且传进来的任务为null)
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
// 因为要加入这个任务,所以判断创建的线程是否存活,存活表示此线程已经在运行,不是新的线程,存活则抛出异常
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
// 加入工作workers中,workers中包含线程池中所有的工作线程,只有持有锁时才能访问
workers.add(w);
// 获取当前工作线程数
int s = workers.size();
// 如果大于最大线程数,将最大线程数重新赋值
if (s > largestPoolSize)
largestPoolSize = s;
// worker的添加工作状态改为true
workerAdded = true;
}
} finally {
// 释放锁
mainLock.unlock();
}
// 如果添加worker工作完成,启动线程,并修改线程启动状态
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
// //判断线程有没有启动成功,没有则调用addWorkerFailed方法
if (! workerStarted)
// 将线程从workers中删除,该方法中也是用了重入锁,保证线程安全,尝试终止
addWorkerFailed(w);
}
// 返回线程启动状态
return workerStarted;
}
//3.addWorker方法中,workerAdded为true, 调用了start();
public void run() {
runWorker(this);
}
final void runWorker(Worker w) {
//获取当前线程
Thread wt = Thread.currentThread();
//获取worker里的任务
Runnable task = w.firstTask;
//将worker实例的任务赋值为null
w.firstTask = null;
/*
*unlock方法会调用AQS的release方法
*release方法会调用具体实现类也就是Worker的tryRelease方法
*也就是将AQS状态置为0,允许中断
*/
w.unlock(); // allow interrupts
//是否突然完成
boolean completedAbruptly = true;
try {
//每个worker实例的task不为空,或者通过getTask获取的不为空(从阻塞队列中take一个) 循环执行
while (task != null || (task = getTask()) != null) {
//获取锁
w.lock();
/*获取线程池的控制状态,至少要大于STOP状态
*如果状态不对,检查当前线程是否中断并清除中断状态,并且再次检查线程池状态是否大于STOP
*如果上述满足,检查该对象是否处于中断状态,不清除中断标记
*/
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
//中断对象
wt.interrupt();
try {
//执行前的方法,由子类具体实现
beforeExecute(wt, task);
Throwable thrown = null;
try {
//执行任务 也就是execute传递过来的runnable对象,调用run方法
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
task = null;
//已完成任务数+1
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
//处理并退出当前worker
processWorkerExit(w, completedAbruptly);
}
}
package java.util.concurrent;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.*;
/**
* ThreadPoolExecutor 线程池
* @since 1.5
* @author Doug Lea
*/
public class ThreadPoolExecutor extends AbstractExecutorService {
/**
* 用来标记线程池状态(高3位),线程个数(低29位)
* RUNNING -> (高3位):11100000000000000000000000000000
* ctl = 11100000000000000000000000000000|0 = 11100000000000000000000000000000
* 默认是RUNNING状态,线程个数为0
*/
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
/**
*线程个数掩码位数,并不是所有平台int类型是32位,所以准确说是具体平台下Integer的二进制位数-3后的剩余位数才是线程的个数
*/
private static final int COUNT_BITS = Integer.SIZE - 3;
//线程最大个数(低29位)00011111111111111111111111111111
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
/**
*高3位表示线程池的状态,低29位表示线程池的工作线程数量
*线程池状态转换:
1.RUNNING -> SHUTDOWN:显式调用 shutdown() 方法,或者隐式调用了 finalize(),它里面调用了 shutdown() 方法。
2.RUNNING or SHUTDOWN -> STOP:显式调用 shutdownNow() 方法时候。
3.SHUTDOWN -> TIDYING:当线程池和任务队列都为空的时候。
4.STOP -> TIDYING:当线程池为空的时候。
5.TIDYING -> TERMINATED:当 terminated() hook 方法执行完成时候。
*/
// runState is stored in the high-order bits
// (高3位):11100000000000000000000000000000
// 接受新任务并且处理阻塞队列里的任务;
private static final int RUNNING = -1 << COUNT_BITS;
// (高3位):00000000000000000000000000000000
// 拒绝新任务但是处理阻塞队列里的任务;
private static final int SHUTDOWN = 0 << COUNT_BITS;
// (高3位):00100000000000000000000000000000
// 拒绝新任务并且抛弃阻塞队列里的任务,同时会中断正在处理的任务;
private static final int STOP = 1 << COUNT_BITS;
// (高3位):01000000000000000000000000000000
// 所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为 0,将要调用 terminated 方法;
private static final int TIDYING = 2 << COUNT_BITS;
// (高3位):01100000000000000000000000000000
// 终止状态,terminated方法调用完成以后的状态。
private static final int TERMINATED = 3 << COUNT_BITS;
// Packing and unpacking ctl
//获取高三位 运行状态 CAPACITY:00011111111111111111111111111111 ~CAPACITY: 11100000000000000000000000000
//c & 11100000000000000000000000000 -> XXX0000000000000000000000000000000 也是就c的高三位运行状态
private static int runStateOf(int c) { return c & ~CAPACITY; }
//获取低29位 线程个数 CAPACITY:00011111111111111111111111111111
//
private static int workerCountOf(int c) { return c & CAPACITY; }
//计算ctl新值,线程状态 与 线程个数
//首先线程状态rs 低29位都是0 wc 线程个数:高3位都是0 所以ctlOf 得到的是rs的高三位wc线程个数的低29位
private static int ctlOf(int rs, int wc) { return rs | wc; }
/*
* 由于任务线程计数器不会为负数,所以比较状态时,就不必要解包ctl
* 第一个状态是否<第二个状态
*/
private static boolean runStateLessThan(int c, int s) {
return c < s;
}
//第一个状态是否>=第二个状态
private static boolean runStateAtLeast(int c, int s) {
return c >= s;
}
// 判断这个状态是否在运行 也就是状态小于SHUTDOWN ? 这里为什么不用=RUNNING?
private static boolean isRunning(int c) {
return c < SHUTDOWN;
}
/**
* 初始化的时候,低29位都是0 ,并且线程池的容量 (1<< 29)-1 尝试CAS 任务线程数+1
*/
private boolean compareAndIncrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect + 1);
}
/**
* 尝试CAS任务线程数-1
*/
private boolean compareAndDecrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect - 1);
}
/**
* 在任务线程中断结束时,调用processWorkerExit方法,用于清除当前中断任务线程计数,在getTask也有用到。
*/
private void decrementWorkerCount() {
//无限循环调用清除所有的任务线程数,直到此操作CAS成功执行。
do {} while (! compareAndDecrementWorkerCount(ctl.get()));
}
/**
* 任务队列用于放提交到线程池的任务,并有任务线程处理。我们一般不用
poll返回null来判断队列是否为null,而是用isEmpty方法判断队列是否为空,
以便判断是否应该将线程池状态从SHUTDOWN切换到TIDYING。但是强烈建议在用
DelayQueues作为任务队列时可以用poll,由于poll的方法允许返回null,即使
在延时时间过期时,返回为非null。
*/
private final BlockingQueue<Runnable> workQueue;
/**
* 当需要访问任务线程集合和相关的记录需要,加锁。当我们用一个并发集合
排序时,一般情况下,最好使用锁。其中有一个原因为interruptIdleWorkers,
即中断空闲任务线程,这样可以在关闭线程池的过程中,避免中断风暴。
否则退出的任务线程将会并发中断还没有中断的任务线程,即有可能发生中断风暴。
也被用于简单的统计largestPoolSize等。在关闭和立即关闭时,我们需要持有锁,
以便在独立检查中断允许和实际中断状态时,保证任务线程集的稳定性。
*/
private final ReentrantLock mainLock = new ReentrantLock();
/**
* 线程池任务线程集,当持有mainLock锁时,可以访问线程池任务线程集
*/
private final HashSet<Worker> workers = new HashSet<Worker>();
/**
* 等待线程池结束条件 后面的才会执行
*/
private final Condition termination = mainLock.newCondition();
/**
* 在持有mainLock的情况下,追踪最大线程池
*/
private int largestPoolSize;
/**
* 在持有mainLock的情况下,可以访问,completedTaskCount为完成任务计数器,
在任务线程结束时,更新。
*/
private long completedTaskCount;
/*
* 所有用于控制参数被修饰为volatiles,以便正在进行的操作,都是基于最新值,
在不需要锁的情况下,相对于其他动作,依赖于这些参数的可变量同步地改变。
即所有需要引用这些参数的变量或动作,可以立即看到参数最新值。
*/
/**
* ThreadFactory为创建任务线程的工厂。所有任务线程的创建都是在调用addWorker
的过程中,使用线程工厂创建。所有调用线程工厂创建任务线程的使用者,必要
做好添加任务线程失败的心理准备,这也许会影响系统或用户的线程数量限制策略。
即使不作为错误对待,创建任务线程失败,也许导致新任务被拒绝,或一个任务
阻塞在任务队列中。
*
* 即使在创建任务线程是可能会有OutOfMemoryError的错误,我们必须尽量保证
线程池的不变性。这种事情的发生,一般是由在我们创建一个线程的本地栈时,
用户想要关闭线程池,清除任务线程。在没有遇到OutOfMemoryError的情况下,
将会有足够的内存用于清理工作。
*/
private volatile ThreadFactory threadFactory;
/**
* 当线程池饱和或线程池关闭时,拒绝任务处理handler 拒绝策略
*/
private volatile RejectedExecutionHandler handler;
/**
* 线程池空闲任务线程,等待任务的时间。如果当前线程数量大于核心线程池数量,
且allowCoreThreadTimeOut为true,任务线程空闲,允许等待keepAliveTime时间,
以便在这个时间范围内,有任务需要执行
*/
private volatile long keepAliveTime;
/**
* 在当前线程数量大于核心线程池数量的情况下,是否允许空闲任务线程等,
保活keepAliveTime时间,等待任务的到来。
*/
private volatile boolean allowCoreThreadTimeOut;
/**
* 在不允许空闲等待的情况,核心线程池数量,即保活的任务线程最小数量。
如果允许空闲等待,线程池任务线程可能为0。
*/
private volatile int corePoolSize;
/**
* 最大线程池数量,如果容量是有界的,实际为CAPACITY
*/
private volatile int maximumPoolSize;
/**
* 默认的拒绝任务策略,抛出运行时异常
*/
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
/**
* 当调用者调用shutdown和shutdownNow方法时,需要shutdownPerm运行时允许权限,
以便调用者可以权限中断任务线程,在关闭的时候,首先检查调用者是否有
shutdownPerm运行时权限。通过ThreadGroup.checkAccess是否拥有权限。
*
* 实际上调用线程中断(interruptIdleWorkers和interruptWorkers)
忽略SecurityExceptions,意味着尝试中断默认失败。在线程关闭的时候,
除非SecurityManager有不一致的策略(有事允许,有时不允许),否则中断不应该失败。
如果SecurityManager为不一致的策略,线程的中断实际上有可能失败。
*/
private static final RuntimePermission shutdownPerm =
new RuntimePermission("modifyThread");
/* 执行终结器finalizer时要使用的上下文,或为空 */
private final AccessControlContext acc;
/**
* 类Worker主要维护运行任务的线程的中断控制状态,以及其他次要的记帐。该类机会性地扩展了AbstractQueuedSynchronizer,以简化获取和释放围绕每个任务执行的锁的过程。
* 这可以防止旨在唤醒等待任务的工作线程而不是中断正在运行的任务的中断。我们实现了一个简单的不可重入互斥锁,而不是使用ReentrantLock,因为我们不希望工作任务在调用setCorePoolSize之类的池控制方法时能够重新获取锁。
* 另外,为了在线程真正开始运行任务之前禁止中断,我们将锁状态初始化为负值,并在启动时清除它(在runWorker中)。
*/
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
/**
*这个类永远不会被序列化,但是我们提供了一个serialVersionUID来禁止javac警告。
*/
private static final long serialVersionUID = 6138294804551838833L;
/** 此工作线程正在运行。如果工厂失败,则为空。 */
final Thread thread;
/** 要运行的初始任务。可能为空。 */
Runnable firstTask;
/** 记录该线程完成了多少个任务(非整个线程池)。 */
volatile long completedTasks;
/**
* 使用给定的第一个任务和ThreadFactory中的线程创建。
* @param firstTask the first task (null if none)
*/
Worker(Runnable firstTask) {
setState(-1); // 禁止中断runWorker
this.firstTask = firstTask;
//ThreadFacotry.newThread(Runnable)
this.thread = getThreadFactory().newThread(this);
}
/** 将主运行委托给外部的线程池对象处理 */
public void run() {
runWorker(this);
}
// 是否独有
// 值0表示未锁定状态。值1表示锁定状态。
// The value 0 represents the unlocked state.
// The value 1 represents the locked state.
protected boolean isHeldExclusively() {
return getState() != 0;
}
//尝试以独占模式获取。此方法应查询对象的状态是否允许以独占模式获取它,如果允许则获取它。
protected boolean tryAcquire(int unused) {
//获取worker 的 stateOffset状态偏移量的值是否是0,如果是0,更新为1
if (compareAndSetState(0, 1)) {
//设置当前拥有独占访问权限的线程。null 参数表示没有线程拥有访问权限。此方法不会强制任何同步或volatile字段访问。
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
//尝试释放
protected boolean tryRelease(int unused) {
//设置没有任何线程拥有独占访问权限
setExclusiveOwnerThread(null);
//设置状态为0
setState(0);
return true;
}
//加锁
public void lock() { acquire(1); }
//尝试获取锁
public boolean tryLock() { return tryAcquire(1); }
//解锁
public void unlock() { release(1); }
//判断是否锁定 ,isHeldExclusively()是否被独享
public boolean isLocked() { return isHeldExclusively(); }
//,中断此线程
void interruptIfStarted() {
Thread t;
//当状态>=0的时候 线程不为空,且没有被中断
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
}
/*
* 控制状态设置方法
*/
/**
* 从运行的状态过渡到targetState
* 如果当前已经大于了targetState,就什么都不做。
将运行状态转换为给定目标,或者如果已经至少是给定目标,则将其单独保留。
targetState参数的使用值只有两个:SHUTDOWN与STOP
SHUTDOWN值为0
STOP值为1<<29 = 2^29。 二进制表示的话1后面29个0
假设传的参数是SHUTDOWN:
ctlOf(targetState, workerCountOf(c)) = workerCountOf(c) > 0,一般就是线程池的个数
假设传的参数是STOP: 2^29
ctlOf(targetState, workerCountOf(c)) = 2^29 + 2 , 为STOP状态
*/
private void advanceRunState(int targetState) {
for (;;) {
int c = ctl.get();//当前运行状态
//如果当前状态已经至少是目标状态 或者 将当前状态改成目标状态并且记录总worker数量成功 结束死循环
if (runStateAtLeast(c, targetState) ||
ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
break;
}
}
/**
* 在以下情况将线程池变为TERMINATED终止状态
* shutdown 且 正在运行的worker 和 workQueue队列 都empty
* stop 且 没有正在运行的worker
*
* 这个方法必须在任何可能导致线程池终止的情况下被调用,如:
* 减少worker数量
* shutdown时从queue中移除任务
*
* 这个方法不是私有的,所以允许子类ScheduledThreadPoolExecutor调用
*/
final void tryTerminate() {
//这个for循环主要是和进入关闭线程池操作的CAS判断结合使用的
for (;;) {
/**
* 线程池是否需要终止
* 如果以下3中情况任一为true,return,不进行终止
* 1、还在运行状态
* 2、状态是TIDYING、或 TERMINATED,已经终止过了
* 3、SHUTDOWN 且 workQueue不为空
*/
int c = ctl.get(); //状态
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
/**
* 只有shutdown状态 且 workQueue为空,或者 stop状态能执行到这一步
* 如果此时线程池还有线程(正在运行任务,正在等待任务)
* 中断唤醒一个正在等任务的空闲worker
* 唤醒后再次判断线程池状态,会return null,进入processWorkerExit()流程
*/
if (workerCountOf(c) != 0) { // 有资格终止
/**
* 在这种情况下,最多有一个worker被中断,为了传播shutdown信号,以免所有的线程都在等待???
* 为保证线程池最终能终止,这个操作总是中断一个空闲worker
* 而shutdown()中断所有空闲worker,来保证空闲线程及时退出
*
*/
interruptIdleWorkers(ONLY_ONE);
return;
}
/**
* 如果状态是SHUTDOWN,workQueue也为空了,正在运行的worker也没有了,开始terminated
*/
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//CAS:将线程池的ctl变成TIDYING(所有的任务被终止,workCount为0,为此状态时将会调用 //terminated()方法),期间ctl有变化就会失败,会再次for循环
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
terminated();
} finally {
ctl.set(ctlOf(TERMINATED, 0));//将线程池的ctl变成TERMINATED
//Condition唤醒调用了 等待线程池终止的线程 awaitTermination()
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
// 如果上面的CAS判断false,再次循环
}
}
/*
* 判断调用者是否有权限shutdown线程池
*/
/**
* 如果有安全管理器,请确保调用方具有关闭线程的权限(请参阅shutdownPerm)。如果这通过了,另外还要确保允许调用方中断每个工作线程。即使第一次检查通过,如果SecurityManager特别处理一些线程,这也可能不是真的。
*/
private void checkShutdownAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(shutdownPerm);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
security.checkAccess(w.thread);
} finally {
mainLock.unlock();
}
}
}
/**
* 中断所有线程,包括正在运行的线程。忽略SecurityExceptions(在这种情况下,某些线程可能保持不间断)
*/
private void interruptWorkers() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
/**
其中会判断worker的AQS state是否大于0,即worker是否已经开始运作,再调用Thread.interrupt()需要注意的是,对于运行中的线程调用Thread.interrupt()并不能保证线程被终止,task.run()内部可能捕获了InterruptException,没有上抛,导致线程一直无法结束
*/
w.interruptIfStarted();
} finally {
mainLock.unlock();
}
}
/**
* 中断在等待任务的线程(没有上锁的空闲线程),中断唤醒后,可以判断线程池状态是否变化来决定是否继续
*
* onlyOne如果为true,最多interrupt一个worker
* 只有当终止流程已经开始,但线程池还有worker线程时,tryTerminate()方法会做调用onlyOne为true的调用
* (终止流程已经开始指的是:shutdown状态 且 workQueue为空,或者 stop状态)
* 在这种情况下,最多有一个worker被中断,为了传播shutdown信号,以免所有的线程都在等待
* 为保证线程池最终能终止,这个操作总是中断一个空闲worker
* 而shutdown()中断所有空闲worker,来保证空闲线程及时退出
*/
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
//1、线程是否已经被中断,是就什么都不做
//2、worker.tryLock() 是否成功
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
/**
* 常见形式的interruptedleworkers,以避免记住布尔参数的含义。
*/
private void interruptIdleWorkers() {
interruptIdleWorkers(false);
}
private static final boolean ONLY_ONE = true;
/*
* Misc utilities, most of which are also exported to
* ScheduledThreadPoolExecutor
*/
/**
* 为给定的命令调用被拒绝的执行处理程序。受保护的包供ScheduledThreadPoolExecutor使用。
*/
final void reject(Runnable command) {
handler.rejectedExecution(command, this);
}
/**
* 在调用shutdown时执行运行状态转换之后的任何进一步清理。这里是no操作,但ScheduledThreadPoolExecutor用于取消延迟的任务。
*/
void onShutdown() {
}
/**
* ScheduledThreadPoolExecutor在关闭期间启用运行任务所需的状态检查。
*
* @param shutdownOK 如果 SHUTDOWN 则返回true
*/
final boolean isRunningOrShutdown(boolean shutdownOK) {
获取高三位 运行状态
int rs = runStateOf(ctl.get());
// RUNNING状态或(线程池处于SHUTDOWN状态并且参数shutdownOK为true),返回true
return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
}
/**
* 调用队列的drainTo一次当前队列的元素到taskList,
* 可能失败,如果调用drainTo后队列海不为空,则循环删除,并添加到taskList
*/
private List<Runnable> drainQueue() {
BlockingQueue<Runnable> q = workQueue;
ArrayList<Runnable> taskList = new ArrayList<Runnable>();
//一次性从BlockingQueue获取所有可用的数据对象(还可以指定获取数据的个数),通过该方法, //可以提升获取数据效率;不需要多次分批加锁或释放锁。
q.drainTo(taskList);
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
*/
/**
* 添加worker 第一个任务 ; 是否核心
*/
private boolean addWorker(Runnable firstTask, boolean core) {
//外部循环标记
retry:
//外层死循环
for (;;) {
//获取线程池控制状态
int c = ctl.get();
//获取 线程池的运行状态
int rs = runStateOf(c);
// 仅在必要时检查队列是否为空。
/**
*1.如果线程池runState至少已经是SHUTDOWN
*2. 有一个是false则addWorker失败,看false的情况
* - runState==SHUTDOWN,即状态已经大于SHUTDOWN了
* - firstTask为null,即传进来的任务为空,结合上面就是runState是SHUTDOWN,但是
* firstTask不为空,代表线程池已经关闭了还在传任务进来
* - 队列为空,既然任务已经为空,队列为空,就不需要往线程池添加任务了
*/
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
//内层死循环
for (;;) {
//获取线程池的线程个数
int wc = workerCountOf(c);
// 如果是核心的 线程个数大于核心数就不添加
//如果非核心,线程个数大于最大线程池数量就不添加
//返回false
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//增加workerCount +1 (原子操作)
if (compareAndIncrementWorkerCount(c))
// 如果增加成功,则直接返回
break retry;
c = ctl.get(); // 失败重新获取线程池ctl
// 判断当前runState与最开始rs是否相等,不相等说明状态已经被修改,返回重新执行
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
// 根据firstTask创建Worker开始执行任务
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
// 使用重入锁的目的是因为workers使用的是 HashSet线程不安全
final ReentrantLock mainLock = this.mainLock;
// 加锁
mainLock.lock();
try {
//持有锁时重新检查。在ThreadFactory失败或获取锁之前关闭时退出。
int rs = runStateOf(ctl.get());
// rs < SHUTDOWN 说明线程池正在处于运行状态,rs =SHUTDOWN firstTask //为空,其中firstTask 为空表示只是新建线程但没有任务需要执行
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
// 因为要加入这个任务,所以判断创建的线程是否存活,存活表示此线程已经在运行,不是新的线程,存活则抛出异常
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
// 加入worker中,workers中包含线程池中所有的工作线程,只有持有锁时才能访问
workers.add(w);
// 获取当前工作线程数
int s = workers.size();
// 如果大于最大线程数,将最大线程数重新赋值
if (s > largestPoolSize)
largestPoolSize = s;
// worker的添加工作状态改为true
workerAdded = true;
}
} finally {
// 释放锁
mainLock.unlock();
}
// 如果添加worker工作完成,启动线程,并修改线程启动状态
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
// //判断线程有没有启动成功,没有则调用addWorkerFailed方法
if (! workerStarted)
// 将线程从workers中删除,该方法中也是用了重入锁,保证线程安全
addWorkerFailed(w);
}
// 返回线程启动状态
return workerStarted;
}
/**
* addWorker方法添加worker失败,并且没有成功启动任务的时候,就会调用此方法,将任务从workers中移除,并 * 且workerCount做-1操作。
*/
private void addWorkerFailed(Worker w) {
//重入锁
final ReentrantLock mainLock = this.mainLock;
//获取锁
mainLock.lock();
try {
//如果worker不为null
if (w != null)
//workers移除worker
workers.remove(w);
//通过CAS操作,workerCount-1
decrementWorkerCount();
//当对线程池执行了非正常成功逻辑的操作时,都会需要执行tryTerminate尝试终止线程池
tryTerminate();
} finally {
//释放锁
mainLock.unlock();
}
}
/**
* 整个线程结束时调用,线程退出操作。统计整个线程池完成的任务个数之类的工作
*
* @param w the worker
* @param completedAbruptly if the worker died due to user exception
*/
private void processWorkerExit(Worker w, boolean completedAbruptly) {
/*
*completedAbruptly:在runWorker出现,代表是否突然完成的意思
*也就是在执行任务过程当中出现异常,就会突然完成,传true
*
*如果是突然完成,需要通过CAS操作,workerCount-1
*不是突然完成,则不需要-1,因为getTask方法当中已经-1
*
*下面的代码注释貌似与代码意思相反了
*/
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount();
//生成重入锁
final ReentrantLock mainLock = this.mainLock;
//获取锁
mainLock.lock();
try {
//线程池统计的完成任务数completedTaskCount加上worker当中完成的任务数
completedTaskCount += w.completedTasks;
//从HashSet中移除
workers.remove(w);
} finally {
//释放锁
mainLock.unlock();
}
//因为上述操作是释放任务或线程,所以会判断线程池状态,尝试终止线程池
tryTerminate();
//获取线程池的控制状态
int c = ctl.get();
//判断runState是否小于STOP,即是RUNNING或者SHUTDOWN
//如果是RUNNING或者SHUTDOWN,代表没有成功终止线程池
if (runStateLessThan(c, STOP)) {
/*
*是否突然完成
*如若不是,代表已经没有任务可获取完成,因为getTask当中是while循环
*/
if (!completedAbruptly) {
/*
*allowCoreThreadTimeOut:是否允许core thread超时,默认false
*min-默认是corePoolSize
*/
//允许core thread超时并且队列不为空
//min为0,即允许core thread超时,这样就不需要维护核心核心线程池了
//如果workQueue不为空,则至少保持一个线程存活
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
if (min == 0 && ! workQueue.isEmpty())
min = 1;
//如果workerCount大于min,则表示满足所需,可以直接返回
if (workerCountOf(c) >= min)
return; // replacement not needed
}
//关键这在这,加入一条firstTask为null的非核心线程任务,替换当前线程
addWorker(null, false);
}
}
/**
* 只是在线程从工作队列 poll 任务时,加上了超时限制,如果线程在 keepAliveTime 的时间内 poll 不到任务,那我就认为这条线程没事做,可以干掉了
*/
private Runnable getTask() {
//标志是否获取任务超时
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
//获取线程池的控制状态
int c = ctl.get();
//获取线程池的runState
int rs = runStateOf(c);
/*
*判断线程池的状态,出现以下两种情况
*1、runState大于等于SHUTDOWN状态
*2、runState大于等于STOP或者阻塞队列为空
*将会通过CAS操作,进行workerCount-1并返回null
*/
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
//获取线程池的workerCount
int wc = workerCountOf(c);
/*
*allowCoreThreadTimeOut:是否允许core Thread超时,默认false
*workerCount是否大于核心线程数
* 此时timed 表示
*/
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
/*
*1、wc大于maximumPoolSize或者已超时
*2、队列不为空时保证至少有一个任务
*/
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
/*
*通过CAS操作,workerCount-1
*能进行-1操作,证明wc大于maximumPoolSize或者已经超时
*/
if (compareAndDecrementWorkerCount(c))
//-1操作成功,返回null
return null;
//-1操作失败,继续循环
continue;
}
try {
/*
*wc大于核心线程池
*执行poll方法
*小于核心线程池
*执行take方法
*/
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
//判断任务不为空返回任务
if (r != null)
return r;
//获取一段时间没有获取到,获取超时,设置超市标志为true
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
/**
* 该方法的作用就是去执行任务
*/
final void runWorker(Worker w) {
//获取当前线程
Thread wt = Thread.currentThread();
//获取worker里的任务
Runnable task = w.firstTask;
//将worker实例的任务赋值为null
w.firstTask = null;
/*
*unlock方法会调用AQS的release方法
*release方法会调用具体实现类也就是Worker的tryRelease方法
*也就是将AQS状态置为0,允许中断
*/
w.unlock(); // allow interrupts
//是否突然完成
boolean completedAbruptly = true;
try {
//worker实例的task不为空,或者通过getTask获取的不为空
while (task != null || (task = getTask()) != null) {
//获取锁
w.lock();
/*获取线程池的控制状态,至少要大于STOP状态
*如果状态不对,检查当前线程是否中断并清除中断状态,并且再次检查线程池状态是否大于STOP
*如果上述满足,检查该对象是否处于中断状态,不清除中断标记
*/
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
//中断改对象
wt.interrupt();
try {
//执行前的方法,由子类具体实现
beforeExecute(wt, task);
Throwable thrown = null;
try {
//执行任务
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
//执行完后调用的方法,也是由子类具体实现
afterExecute(task, thrown);
}
} finally {
//task设置为null
task = null;
//已完成任务数+1
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
//处理并退出当前worker
processWorkerExit(w, completedAbruptly);
}
}
// Public constructors and methods
/**
* 参数 类型 含义
corePoolSize int 核心线程数
maximumPoolSize int 最大线程数
keepAliveTime long 存活时间
unit TimeUnit 时间单位
workQueue BlockingQueue 存放线程的队列
threadFactory ThreadFactory 创建线程的工厂
handler RejectedExecutionHandler 多余的的线程处理器(拒绝策略)
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
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;
}
/**
*在将来的某个时候执行给定的任务。该任务可以在新线程或现有池线程中执行。如果由于该执行器已关闭或已达到其 容量而无法提交以供执行,则该任务将由当前拒绝策略处理
* the task is handled by the current {@code RejectedExecutionHandler}.
*
*
*/
public void execute(Runnable command) {
//需要执行的任务command为空,抛出空指针异常
if (command == null)
throw new NullPointerException();
/*
*执行的流程实际上分为三步
*1、如果运行的线程小于corePoolSize,以用户给定的Runable对象新开一个线程去执行
* 并且执行addWorker方法会以原子性操作去检查runState和workerCount,以防止当返回false的
* 时候添加了不应该添加的线程
*2、 如果任务能够成功添加到队列当中,我们仍需要对添加的线程进行双重检查,有可能添加的线程在前
* 一次检查时已经死亡,又或者在进入该方法的时候线程池关闭了。所以我们需要复查状态,并有有必
* 要的话需要在停止时回滚入列操作,或者在没有线程的时候新开一个线程
*3、如果任务无法入列,那我们需要尝试新增一个线程,如果新建线程失败了,我们就知道线程可能关闭了
* 或者饱和了,就需要拒绝这个任务
*
*/
//获取线程池的状态
int c = ctl.get();
//通过workCountOf方法算workerCount值,小于corePoolSize
if (workerCountOf(c) < corePoolSize) {
//处于运行状态的线程数小于核心线程数,添加任务到worker集合当中
//添加核心任务
if (addWorker(command, true))
//成功返回
return;
//失败的话再次获取线程池的状态
c = ctl.get();
}
/*
* 运行状态的线程数 不小于核心数时,堵塞队列没满
* 线程池还在运行,将新的线程插入阻塞队列中
判断线程池是否正处于RUNNING状态
*是的话添加Runnable对象到workQueue队列当中
*/
if (isRunning(c) && workQueue.offer(command)) {
//再次获取线程池的状态
int recheck = ctl.get();
//再次检查状态
//线程池不处于RUNNING状态,将任务从workQueue队列中移除
if (! isRunning(recheck) && remove(command))
//拒绝任务
reject(command);
//如果此时线程池的工作线程个数为0,加入新的非核心任务
else if (workerCountOf(recheck) == 0)
//添加非核心的worker 为null
addWorker(null, false);
}
//队列满的话,就添加到非核心任务
else if (!addWorker(command, false))
//执行失败则拒绝任务
reject(command);
}
/**
* 当调用shutdown方法时,线程池将不会再接收新的任务,然后将先前放在队列中的任务执行完成。
shutdown和shutdownNow这两个方法的作用都是关闭线程池,流程大致相同,只有几个步骤不同
加锁
检查关闭权限
CAS改变线程池状态
设置中断标志(线程池不在接收任务,队列任务会完成)/中断当前执行的线程
调用onShutdown方法(给子类提供的方法)/获取队列中的任务
解锁
尝试将线程池状态变成终止状态TERMINATED
结束/返回队列中的任务
*
* @throws SecurityException {@inheritDoc}
*/
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
/**
* 立即停止所有的执行任务,并将队列中的任务返回
*
* @throws SecurityException {@inheritDoc}
*/
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
public boolean isShutdown() {
return ! isRunning(ctl.get());
}
/**
* 表示如果此执行程序处于在 shutdown 或 shutdownNow 之后正在终止但尚未完全终止的过程中,则返回 true。
*
* @return {@code true} if terminating but not yet terminated
*/
public boolean isTerminating() {
int c = ctl.get();
return ! isRunning(c) && runStateLessThan(c, TERMINATED);
}
//表示如果关闭后所有任务都已完成,则返回 true
public boolean isTerminated() {
return runStateAtLeast(ctl.get(), TERMINATED);
}
/**接收人timeout和TimeUnit两个参数,用于设定超时时间及单位。当等待超过设定时间时,会监测 *ExecutorService是否已经关闭,若关闭则返回true,否则返回false。一般情况下会和shutdown方法组合使用。
*/
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (;;) {
//如果已经关闭 返回null
if (runStateAtLeast(ctl.get(), TERMINATED))
return true;
if (nanos <= 0)
//如果等待时间<=0 返回false
return false;
//Condition的awaitNanos的实现过程
nanos = termination.awaitNanos(nanos);
}
} finally {
mainLock.unlock();
}
}
/**
* 当这个执行器不再被引用并且没有线程时,调用shutdown。
*/
protected void finalize() {
SecurityManager sm = System.getSecurityManager();
//sm? acc?
if (sm == null || acc == null) {
shutdown();
} else {
PrivilegedAction<Void> pa = () -> { shutdown(); return null; };
AccessController.doPrivileged(pa, acc);
}
}
/**
*
* 设置线程工厂去生成新的线程。
* @throws NullPointerException if threadFactory is null
* @see #getThreadFactory
*/
public void setThreadFactory(ThreadFactory threadFactory) {
if (threadFactory == null)
throw new NullPointerException();
this.threadFactory = threadFactory;
}
/**
* 得到线程工厂
*/
public ThreadFactory getThreadFactory() {
return threadFactory;
}
/**
*
*/
public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
if (handler == null)
throw new NullPointerException();
this.handler = handler;
}
/**
*
*/
public RejectedExecutionHandler getRejectedExecutionHandler() {
return handler;
}
/**
* 设置线程的核心数。这将重写构造函数中设置的任何值。如果新值小于当前值,则多余的现有线程将在下次变为空闲 时终止。如果更大,如果需要,将启动新线程来执行任何排队的任务。
*
* @param corePoolSize 新线程的核心数。
* @throws IllegalArgumentException if {@code corePoolSize < 0}
* @see #getCorePoolSize
*/
public void setCorePoolSize(int corePoolSize) {
//如果核心线程数 <0 抛异常
if (corePoolSize < 0)
throw new IllegalArgumentException();
//新core数 - 对象的core数
int delta = corePoolSize - this.corePoolSize;
//设置对象的core数 为新的core数
this.corePoolSize = corePoolSize;
//工作线程数 大于新的核心线程数 中断workers集合中的空闲任务
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.
//如果新值比原值大,且队列中还存在任务,则马上新增worker来处理
int k = Math.min(delta, workQueue.size());
while (k-- > 0 && addWorker(null, true)) {
if (workQueue.isEmpty())
break;
}
}
}
/**
* Returns the core number of threads.
*
* @return the core number of threads
* @see #setCorePoolSize
*/
public int getCorePoolSize() {
return corePoolSize;
}
/**
* 工作线程数 小于核心线程数 ,预先创建好corePoolSize一个线程。
*
* @return {@code true} if a thread was started
*/
public boolean prestartCoreThread() {
return workerCountOf(ctl.get()) < corePoolSize &&
addWorker(null, true);
}
/**
* 与prestartCoreThread相同,不同之处在于即使corePoolSize为0,也会安排至少启动一个线程。
*/
void ensurePrestart() {
int wc = workerCountOf(ctl.get());
if (wc < corePoolSize)
addWorker(null, true);
else if (wc == 0)
addWorker(null, false);
}
/**
* 启动所有核心线程,导致它们空闲地等待工作。这将覆盖仅在执行新任务时启动核心线程的默认策略。
*
* @return the number of threads started
*/
public int prestartAllCoreThreads() {
int n = 0;
while (addWorker(null, true))
++n;
return n;
}
/**
* 如果此池允许核心线程超时,则返回true;如果在keepAlive时间内没有任务到达,则返回terminate;如果需要,则在新任务到达时替换。如果为true,则应用于非核心线程的相同保持活动策略也适用于核心线程。如果为false(默认值),则不会由于缺少传入任务而终止核心线程。
*
* @return {@code true} if core threads are allowed to time out,
* else {@code false}
*
* @since 1.6
*/
public boolean allowsCoreThreadTimeOut() {
return allowCoreThreadTimeOut;
}
/**
*设置是否允许超时
*
* @param value {@code true} if should time out, else {@code false}
* @throws IllegalArgumentException if value is {@code true}
* and the current keep-alive time is not greater than zero
*
* @since 1.6
*/
public void allowCoreThreadTimeOut(boolean value) {
//如果允许超时,超时时间必须大于0
if (value && keepAliveTime <= 0)
throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
//如果新值和旧值不同 重新赋值,且如果允许,中断workers集合中的空闲任务
if (value != allowCoreThreadTimeOut) {
allowCoreThreadTimeOut = value;
if (value)
interruptIdleWorkers();
}
}
/**
* 设置允许的最大线程数。这将重写构造函数中设置的任何值。如果新值小于当前值,则多余的现有线程将在下次变为空闲时终止。
*
* @param maximumPoolSize the new maximum
* @throws IllegalArgumentException if the new maximum is
* less than or equal to zero, or
* less than the {@linkplain #getCorePoolSize core pool size}
* @see #getMaximumPoolSize
*/
public void setMaximumPoolSize(int maximumPoolSize) {
//最大线程池数量 必须大于0且不小于核心线程数
if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
throw new IllegalArgumentException();
this.maximumPoolSize = maximumPoolSize;
//如果新值小于当前值,则多余的现有线程将在下次变为空闲时终止。
if (workerCountOf(ctl.get()) > maximumPoolSize)
interruptIdleWorkers();
}
/**
*
*/
public int getMaximumPoolSize() {
return maximumPoolSize;
}
/**
* 设置线程在终止之前可以保持空闲的时间限制。如果池中当前的线程数超过核心数,则在等待此时间而不处理任务后,将终止多余的线程。这将重写构造函数中设置的任何值。
*
* @param time the time to wait. A time value of zero will cause
* excess threads to terminate immediately after executing tasks.
* @param unit the time unit of the {@code time} argument
* @throws IllegalArgumentException if {@code time} less than zero or
* if {@code time} is zero and {@code allowsCoreThreadTimeOut}
* @see #getKeepAliveTime(TimeUnit)
*/
public void setKeepAliveTime(long time, TimeUnit unit) {
//如果空闲时间限制 小于0 报错
if (time < 0)
throw new IllegalArgumentException();
//如果空闲时间限制等于0且允许超时 报错
if (time == 0 && allowsCoreThreadTimeOut())
throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
//如果新值小于旧值,多余的现有线程将在下次变为空闲时终止。
long keepAliveTime = unit.toNanos(time);
long delta = keepAliveTime - this.keepAliveTime;
this.keepAliveTime = keepAliveTime;
if (delta < 0)
interruptIdleWorkers();
}
/**
* Returns the thread keep-alive time, which is the amount of time
* that threads in excess of the core pool size may remain
* idle before being terminated.
*
* @param unit the desired time unit of the result
* @return the time limit
* @see #setKeepAliveTime(long, TimeUnit)
*/
public long getKeepAliveTime(TimeUnit unit) {
return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
}
/* User-level queue utilities */
/**
* Returns the task queue used by this executor. Access to the
* task queue is intended primarily for debugging and monitoring.
* This queue may be in active use. Retrieving the task queue
* does not prevent queued tasks from executing.
*
* @return the task queue
*/
public BlockingQueue<Runnable> getQueue() {
return workQueue;
}
/**
* 移除一个任务
*/
public boolean remove(Runnable task) {
boolean removed = workQueue.remove(task);
//以防 关闭或者为空,尝试中断。
tryTerminate(); // In case SHUTDOWN and now empty
return removed;
}
/**
* 尝试从工作队列中删除所有已取消的{@link Future}任务。此方法可以用作对功能没有其他影响的存储回收操作。取消的任务永远不会执行,但可能会累积在工作队列中,直到工作线程可以主动删除它们。相反,调用此方法会尝试立即删除它们。但是,在其他线程的干扰下,此方法可能无法删除任务。
*/
public void purge() {
final BlockingQueue<Runnable> q = workQueue;
try {
Iterator<Runnable> it = q.iterator();
while (it.hasNext()) {
Runnable r = it.next();
if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
it.remove();
}
} catch (ConcurrentModificationException fallThrough) {
// Take slow path if we encounter interference during traversal.
// Make copy for traversal and call remove for cancelled entries.
// The slow path is more likely to be O(N*N).
for (Object r : q.toArray())
if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
q.remove(r);
}
tryTerminate(); // In case SHUTDOWN and now empty
}
/* Statistics */
/**
* 返回池中当前线程数。
*
* @return the number of threads
*/
public int getPoolSize() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
删除isTerminated()&&getPoolSize()>0的罕见且令人惊讶的可能性
return runStateAtLeast(ctl.get(), TIDYING) ? 0
: workers.size();
} finally {
mainLock.unlock();
}
}
/**
* 返回正在积极执行任务的线程的大致数目。
*
* @return the number of threads
*/
public int getActiveCount() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
int n = 0;
for (Worker w : workers)
if (w.isLocked())
++n;
return n;
} finally {
mainLock.unlock();
}
}
/**
* 返回池中同时存在的最大线程数。
*
* @return the number of threads
*/
public int getLargestPoolSize() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
return largestPoolSize;
} finally {
mainLock.unlock();
}
}
/**
* 返回已计划执行的任务的大致总数。由于任务和线程的状态在计算期间可能会动态更改,因此返回的值只是一个近似值。
*
* @return the number of tasks
*/
public long getTaskCount() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
long n = completedTaskCount;
for (Worker w : workers) {
n += w.completedTasks;
if (w.isLocked())
++n;
}
return n + workQueue.size();
} finally {
mainLock.unlock();
}
}
/**
* 返回已完成执行的任务的大致总数。由于任务和线程的状态在计算过程中可能会动态变化,因此返回的值只是一个近似值,但在连续的调用中不会减少。
*
* @return the number of tasks
*/
public long getCompletedTaskCount() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
long n = completedTaskCount;
for (Worker w : workers)
n += w.completedTasks;
return n;
} finally {
mainLock.unlock();
}
}
/**
* 返回标识此池及其状态的字符串,包括运行状态的指示以及估计的工作进程和任务计数。
* 注意一个类的toString方法都要加锁。- -
* @return a string identifying this pool, as well as its state
*/
public String toString() {
long ncompleted;
int nworkers, nactive;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
ncompleted = completedTaskCount;
nactive = 0;
nworkers = workers.size();
for (Worker w : workers) {
ncompleted += w.completedTasks;
if (w.isLocked())
++nactive;
}
} finally {
mainLock.unlock();
}
int c = ctl.get();
String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" :
(runStateAtLeast(c, TERMINATED) ? "Terminated" :
"Shutting down"));
return super.toString() +
"[" + rs +
", pool size = " + nworkers +
", active threads = " + nactive +
", queued tasks = " + workQueue.size() +
", completed tasks = " + ncompleted +
"]";
}
/* Extension hooks */
/**
* 执行前的方法,由子类具体实现
*
* @param t the thread that will run task {@code r}
* @param r the task that will be executed
*/
protected void beforeExecute(Thread t, Runnable r) { }
/**
* Method invoked upon completion of execution of the given Runnable.
* This method is invoked by the thread that executed the task. If
* non-null, the Throwable is the uncaught {@code RuntimeException}
* or {@code Error} that caused execution to terminate abruptly.
*
* 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.
*
*
Note: 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 not
* passed to this method. If you would like to trap both kinds of
* failures in this method, you can further probe for such cases,
* as in this sample subclass that prints either the direct cause
* or the underlying exception if a task has been aborted:
*
*
{@code
* class ExtendedExecutor extends ThreadPoolExecutor {
* // ...
* protected void afterExecute(Runnable r, Throwable t) {
* super.afterExecute(r, t);
* if (t == null && r instanceof Future>) {
* try {
* Object result = ((Future>) r).get();
* } catch (CancellationException ce) {
* t = ce;
* } catch (ExecutionException ee) {
* t = ee.getCause();
* } catch (InterruptedException ie) {
* Thread.currentThread().interrupt(); // ignore/reset
* }
* }
* if (t != null)
* System.out.println(t);
* }
* }}
*
* @param r the runnable that has completed
* @param t the exception that caused termination, or null if
* execution completed normally
*/
protected void afterExecute(Runnable r, Throwable t) { }
/**
* Method invoked when the Executor has terminated. Default
* implementation does nothing. Note: To properly nest multiple
* overridings, subclasses should generally invoke
* {@code super.terminated} within this method.
*/
protected void terminated() { }
/* Predefined RejectedExecutionHandlers */
/**
* 一种被拒绝任务的处理程序,它直接在{@code execute}方法的调用线程中运行被拒绝的任务,除非执行程序已关闭,在这种情况下,该任务将被丢弃。.
只用调用者所在线程来运行任务。
*/
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
/**
* Executes task r in the caller's thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
/**
* 直接抛异常RejectedExecutionException的策略
*/
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
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
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
/**
*一个被拒绝任务的处理程序,它会自动放弃被拒绝的任务。
*/
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
/**
* 被拒绝任务的处理程序,该处理程序丢弃最旧的未处理请求,然后重试{@code execute},除非该执行程序关闭,否则该任务将被丢弃。
*/
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
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.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
//最旧的执行
e.getQueue().poll();
e.execute(r);
}
}
}
}
execute方法
addWorker方法
创建工作线程,并且调用工作线程的runWorker()方法,循环调用工作线程的firstTask或者从阻塞队列中take任务。每次调用完成后删除这个任务。