1.类定义
/**
* 定义ThreadPoolExecutor线程池类
*/
public class ThreadPoolExecutor extends AbstractExecutorService {
/** 线程池内部状态清况 */
//其中AtomicInteger变量ctl的功能非常强大:利用低29位表示线程池中线程数,通过高3位表示线程池的运行状态
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));//AtomicInteger这个类可以通过CAS达到无锁并发,效率比较高
//表示线程池线程数的bit数
private static final int COUNT_BITS = Integer.SIZE - 3; //32-3 = 29
//最大的线程数量,数量是完全够用了
private static final int CAPACITY = (1 << COUNT_BITS) - 1; //00011111*
//高3位为111,该状态的线程池会接收新任务,并处理阻塞队列中的任务;
private static final int RUNNING = -1 << COUNT_BITS;
//高3位为000,该状态的线程池不会接收新任务,但会处理阻塞队列中的任务;
private static final int SHUTDOWN = 0 << COUNT_BITS;
//高3位为001,该状态的线程不会接收新任务,也不会处理阻塞队列中的任务,而且会中断正在运行的任务;
private static final int STOP = 1 << COUNT_BITS;
//高3位为010, 所有的任务都已经终止;
private static final int TIDYING = 2 << COUNT_BITS;
//高3位为011, terminated()方法已经执行完成
private static final int TERMINATED = 3 << COUNT_BITS;
//获取线程池的状态
private static int runStateOf(int c) { return c & ~CAPACITY; }
//获取线程的数量 即低29位所代表的置
private static int workerCountOf(int c) { return c & CAPACITY; }
//组装状态和数量,成为ctl
private static int ctlOf(int rs, int wc) { return rs | wc; }
/**
* 存放提交的任务
*/
private final BlockingQueue<Runnable> workQueue;
/** 线程工厂 */
private volatile ThreadFactory threadFactory;
/** 空闲线程存活时间 默认是临时线程 也可以设置为核心线程 */
private volatile long keepAliveTime;
/** 核心线程数 */
private volatile int corePoolSize;
/** 最大线程数 */
private volatile int maximumPoolSize;
}
2.构造方法
/** 构造方法 */
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);
}
/**
* 构造方法
* @param corePoolSize 线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize
* 即使有其他空闲线程能够执行新来的任务, 也会继续创建线程
* 如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;
* 如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。
* @param maximumPoolSize 线程池中允许的最大线程数。如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize
* 当阻塞队列是无界队列, 则maximumPoolSize则不起作用, 因为无法提交至核心线程池的线程会一直持续地放入workQueue.
* @param keepAliveTime 线程空闲时的存活时间,即当线程没有任务执行时,该线程继续存活的时间;
* 默认情况下,该参数只在线程数大于corePoolSize时才有用, 超过这个时间的空闲线程将被终止;
* @param unit keepAliveTime的单位
* @param workQueue 用来保存等待被执行的任务的阻塞队列
* @param threadFactory 创建线程的工厂,通过自定义的线程工厂可以给每个新建的线程设置一个具有识别度的线程名。默认为DefaultThreadFactory
* @param handler 线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务
* 线程池提供了4种策略:
* AbortPolicy:直接抛出异常,默认策略;
* CallerRunsPolicy:用调用者所在的线程来执行任务;
* DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
* DiscardPolicy:直接丢弃任务;
* 也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略。
*/
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;
}
3.提交任务
/**
* 提交任务到线程池
*/
public void execute(Runnable command) {
if (command == null) //校验非空
throw new NullPointerException();
//获取ctl
int c = ctl.get();
//检查当前线程数是否达到核心线程数的限制
if (workerCountOf(c) < corePoolSize) {
//如果核心线程数未达到,会直接添加一个核心线程
if (addWorker(command, true))
return; //任务添加成功 直接返回
c = ctl.get(); //如果添加任务失败,刷新ctl,进入下一步
}
//检查线程池是否是运行状态,然后将任务添加到等待队列,注意offer是不会阻塞的
if (isRunning(c) && workQueue.offer(command)) {
//任务成功添加到等待队列,再次刷新ctl
int recheck = ctl.get();
//如果线程池不是运行状态,则将刚添加的任务从队列移除并执行拒绝策略
if (! isRunning(recheck) && remove(command))
reject(command);
//判断当前线程数量,如果线程数量为0,则添加一个非核心线程,并且不指定首次执行任务
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//添加非核心线程,指定首次执行任务,如果添加失败,执行异常策略
else if (!addWorker(command, false))
reject(command);
}
3.1 addWorker详解
/**
* 添加一个任务 返回添加结果
* @param firstTask 待添加任务
* @param core 是否添加核心线程
*/
private boolean addWorker(Runnable firstTask, boolean core) {
//相当于goto
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
//如果线程池的状态到了SHUTDOWN或者之上的状态时候,只有一种情况还需要继续添加线程,
//那就是线程池已经SHUTDOWN,但是队列中还有任务在排队,而且不接受新任务(所以firstTask必须为null)
//这里还继续添加线程的初衷是,加快执行等待队列中的任务,尽快让线程池关闭
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
//传入的core的参数,唯一用到的地方,如果线程数超过理论最大容量,如果core是true跟最大核心线程数比较,否则跟最大线程数比较
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//通过CAS自旋,增加线程数+1,增加成功跳出双层循环,继续往下执行
if (compareAndIncrementWorkerCount(c))
break retry;
//检测当前线程状态如果发生了变化,则继续回到retry,重新开始循环
c = ctl.get();
if (runStateOf(c) != rs)
continue retry;
}
}
//走到这里,说明我们已经成功的将线程数+1了,但是真正的线程还没有被添加
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
//添加线程,Worker是继承了AQS,实现了Runnable接口的包装类
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
//到这里开始加锁
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
int rs = runStateOf(ctl.get());
//检查线程状态,还是跟之前一样,只有当线程池处于RUNNING,
// 或者处于SHUTDOWN并且firstTask==null的时候,这时候创建Worker来加速处理队列中的任务
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
//线程只能被start一次
if (t.isAlive())
throw new IllegalThreadStateException();
//workers是一个HashSet,添加我们新增的Worker
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}