Java中的线程池相信大家都很熟悉,不熟悉的朋友可以看我的另一篇博文Java线程池类型以及execute和submit方法的区别。本文主要针对线程池核心类ThreadPoolExecutor中的常用重要方法进行源码解析。
ThreadPoolExecutor中代表线程池状态的属性
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
/**
* 获取线程池状态
*/
private static int runStateOf(int c) { return c & ~CAPACITY; }
/**
* 获取线程池中的线程数量
*/
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
-
ctl属性作为AtomicInteger类存放了类中的两种信息。在其中由高3位来保存线程池的状态,后29位来保存此时线程池中的Woker类线程数量。因此在后面给出的runStateOf()和workerCountOf()方法分别是查看线程状态和线程数量的方法。
-
RUNNING状态说明正在执行队列中的任务,同时也可以接受新添加的任务
-
SHUTDOWN状态不会接受新添加的任务,但是仍然会处理队列中未完成的任务
-
STOP状态不会接受新添加的任务,也不会处理队列中的任务,而正在执行的任务也会被打断
-
TIDYING状态标识着所有的任务已经终止,线程池中的Worker线程为0。也就是STOP状态在清理完所有线程之后就会进入该状态,同时在SHUTDOWN状态中队列为空以及线程清理完毕之后也会直接进入这个状态,在这个阶段会循环执行terminated()方法
-
TERMINATED状态是线程池最后的状态。在执行完terminated()方法后,就会进入改状态,说明该线程池已经完全停止
ThreadPoolExecutor中代表线程池基本信息的属性
// 标识线程池中允许存活最少的核心线程数量。但是需要注意的是,如果allowCoreThreadTimeOut设置为true(默认为false),那么所有空闲线程(核心和非核心线程)的存活时间只有keepAliveTime。也就是说,当allowCoreThreadTimeOut为true时候,线程池最小的线程数量为0
private volatile int corePoolSize;
// 记录线程池中存在过的最大线程数量
private int largestPoolSize;
// 代表线程池中最大的线程数量
private volatile int maximumPoolSize;
// 记录已完成的任务总数
private long completedTaskCount;
// 若allowCoreThreadTimeOut为true,则池中所有空闲线程(包括核心线程)的最大等待时间
// 若allowCoreThreadTimeOut为false,池中超过corePoolSize数量的空闲线程(非核心线程)的最大等待时间
// 空闲超过最大等待时间则销毁
private volatile long keepAliveTime;
// 是否允许启用核心线程最大等待时间。false为不启用,则空闲的核心线程不会被销毁
private volatile boolean allowCoreThreadTimeOut;
// 存放任务的工作队列
private final BlockingQueue<Runnable> workQueue;
// 存放线程的Set集合
private final HashSet<Worker> workers = new HashSet<Worker>();
// 可重入锁
private final ReentrantLock mainLock = new ReentrantLock();
// 可重入锁的Condition队列
private final Condition termination = mainLock.newCondition();
// 创建线程的工厂
private volatile ThreadFactory threadFactory;
// 作为线程池中在不能接受任务的时候的拒绝策略
private volatile RejectedExecutionHandler handler;
Worker内部类
/**
* 可以看到Worker类继承了AbstractQueuedSynchronizer(AQS)类,而类中大部分的方法都是直接重写或者调用AQS中的方法
* 同时还实现了Runnable接口,可以将Worker的实例对象看作是一个线程
* 不熟悉的AQS的朋友建议先去了解下,再来了解这个Worker
*/
private final class Worker extends AbstractQueuedSynchronizer implements Runnable
{
private static final long serialVersionUID = 6138294804551838833L;
// 要运行的线程
final Thread thread;
// 要执行的任务
Runnable firstTask;
// 完成的任务数量
volatile long completedTasks;
/**
* 构造方法
*/
Worker(Runnable firstTask) {
setState(-1);
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this); // threadFactory创建线程
}
/**
* 将运行线程任务工作委托给外部类ThreadPoolExecutor的runWorker方法
*/
public void run() {
runWorker(this);
}
/**
* 0表示解锁状态
* 1表示锁定状态。
*/
protected boolean isHeldExclusively() {
return getState() != 0;
}
/**
* 通尝试获取锁(只是通过CAS操作改变状态,并没有涉及到唤醒阻塞线程的操作)
*/
protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
/**
* 尝试释放锁(只是改变状态,并没有涉及到唤醒阻塞线程的操作)
*/
protected boolean tryRelease(int unused) {
setExclusiveOwnerThread(null);
setState(0);
return true;
}
/**
* 获取锁
*/
public void lock() { acquire(1); }
/**
* 尝试获取锁
*/
public boolean tryLock() { return tryAcquire(1); }
/**
* 释放锁
*/
public void unlock() { release(1); }
/**
* 线程是否处于锁定状态
*/
public boolean isLocked() { return isHeldExclusively(); }
/**
* 中断已经开始执行任务的线程
*/
void interruptIfStarted() {
Thread t;
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
}
了解完ThreadPoolExecutor中主要的内部属性和结构,接下来就针对线程池最常用的,也是最核心的方法进行源码讲解分析。
execute()
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) { // 池中线程数小于corePoolSize,则添加新的线程
if (addWorker(command, true)) // 添加自带command任务的新线程
return;
c = ctl.get();
}
// 池中线程数量大于等于corePoolSize,或者添加线程失败,先查看线程池状态
if (isRunning(c) && workQueue.offer(command)) { // 处于运行状态,则添加新的任务command进入任务队列
int recheck = ctl.get();
// 双重保险,再次查看线程池状态
if (! isRunning(recheck) && remove(command)) // 不处于运行状态,则移除刚添加进任务队列的新任务command
reject(command); // 拒绝执行command任务
else if (workerCountOf(recheck) == 0) // 池中线程数量为0
addWorker(null, false); // 添加新的空任务线程
}
else if (!addWorker(command, false)) // 不处于运行状态,或者添加任务进队列失败,则添加自带command任务的新线程
reject(command); // 添加线程失败,拒绝执行command任务
}
- addWorker()方法添加新线程:
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) { // 外部自旋
int c = ctl.get();
int rs = runStateOf(c);
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty())) // 线程池不处于运行状态,而且任务队列为空,则添加线程失败
return false;
for (;;) { // 内部自旋
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize)) // 池中线程数量大于等于池的最大容量,或者大于等于指定的容量,则添加线程失败
return false;
if (compareAndIncrementWorkerCount(c)) // 采用CAS操作,对池中线程数量加1
break retry; // 加1成功,则打破内外部自旋
c = ctl.get();
if (runStateOf(c) != rs) // 在内部自旋过程中,线程状态已改变,则重新执行外部自旋
continue retry;
}
}
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 {
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) { // 再次检查线程池状态,处于运行状态,或者SHUTDOWN状态而且任务为空
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) { // 添加线程成功
t.start(); // 启动线程,执行t线程中的run方法
workerStarted = true; // 标识该线程已启动
}
}
} finally {
if (! workerStarted) // 线程启动失败
addWorkerFailed(w); // 从线程集合中删除新添加的线程,相当于回滚
}
return workerStarted;
}
- new Worker(firstTask)构造方法新建线程:
Worker(Runnable firstTask) {
setState(-1);
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this); // 将Worker实例对象run方法作为线程执行的任务
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
- addWorkerFailed()方法回滚操作:
private void addWorkerFailed(Worker w) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (w != null)
workers.remove(w); // 删除已添加的线程
decrementWorkerCount(); // 池中线程数量减一
tryTerminate(); // 尝试将线程池状态转换为TERMINATED。(转换成功的提前是:线程池为SHUTDOWN或者STOP,而且池中的线程和任务队列都已清空)
} finally {TER
mainLock.unlock();
}
}
了解了往线程池中添加线程的过程,我们再来看,线程池中是如何调用线程去执行任务的。
- run()方法将运行线程任务工作委托给外部的runWorker方法去执行:
public void run() {
runWorker(this);
}
final void runWorker(Worker w) {
Thread wt = Thread.currentThread(); // 当前线程
Runnable task = w.firstTask; // w线程本身自带的任务
w.firstTask = null;
w.unlock(); // 设置state为0、以及占用锁的线程为空,允许中断(注意,unlock方法已被重写,并不是执行AQS类中的释放唤醒线程的方法)
boolean completedAbruptly = true; // 标识任务是否因为异常而终止执行,默认为是
try {
while (task != null || (task = getTask()) != null) { // 若线程本身自带的任务不为空,则执行该任务;否则,从任务队列中获取任务执行(线程在此while循环中不断获取并执行任务)
w.lock(); // 设置state为1,以及设置占用锁的线程为当前线程(注意,lock方法已被重写)
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted()) // 线程池状态处于TIDYING或者TERMINATED状态,而且当前线程未被中断
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; // 任务完成,赋值为空,跳出while循环
w.completedTasks++; // 该线程完成任务数量加1
w.unlock();
}
}
completedAbruptly = false; // 更新标识,执行任务期间没有异常
} finally {
processWorkerExit(w, completedAbruptly); // while循环结束,工作线程没有获取到任务,说明线程池已经处于非运行状态,或者工作线程等待超时,则销毁工作线程
}
}
- getTask()方法从任务队列中获取任务:
private Runnable getTask() {
boolean timedOut = false;
for (;;) { // 自旋
int c = ctl.get();
int rs = runStateOf(c);
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { // 线程池处于非RUNNING状态,而且任务队列为空(即没有要执行的任务)
decrementWorkerCount(); // 池中线程数量减1
return null;
}
int wc = workerCountOf(c);
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; // 若为true,说明allowCoreThreadTimeOut为true,或者池中线程数量大于核心线程数量;否则为false
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) { // 主要从自旋的超时等待进行判断
if (compareAndDecrementWorkerCount(c)) // 线程空闲超时,池中线程数量减1,并在之后的方法中销毁
return null;
continue;
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : // 需要限制线程最大空闲时间,如果超过时间仍然获取不到任务,则获取到的任务为空
workQueue.take(); // 不需要限制线程最大空闲时间,无论如何都要获取到任务
if (r != null)
return r; // 获取到任务后返回
timedOut = true; // 没有获取到任务,设置等待超时为true
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
- processWorkerExit()方法销毁线程:
private void processWorkerExit(Worker w, boolean completedAbruptly) {
if (completedAbruptly) // w线程中的任务执行异常
decrementWorkerCount(); // 池中线程数减1
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
workers.remove(w); // 从线程集合中删除w线程(销毁w线程)
} finally {
mainLock.unlock();
}
tryTerminate(); // 尝试将线程池的状态转换为TERMINATED
int c = ctl.get();
if (runStateLessThan(c, STOP)) { // 线程池处于RUNNING或者SHUTDOWN状态
if (!completedAbruptly) { // w线程正常执行完成任务
int min = allowCoreThreadTimeOut ? 0 : corePoolSize; // 判断是否设置allowCoreThreadTimeOut。若为true则说明,线程池中最小空闲线程数量为0,否则为corePoolSize
if (min == 0 && ! workQueue.isEmpty()) // min为0,而且任务队列不为空(仍然存在等待执行的任务)
min = 1; // min设置为1(至少保留一个线程去执行等待中的任务)
if (workerCountOf(c) >= min) // 池中线程数量大于min
return; // 直接返回
}
addWorker(null, false); // 池中线程数量小于min,则添加新的空任务线程
}
}
到此,关于线程池的添加线程,以及其中调用线程执行任务的源码分析结束了。
但本文内容仍未结束,因为线程池启动了,总是要关的。
shutdown()
/**
* 有序关闭线程池。该过程中会中断池中的空闲线程,不会影响正在执行的线程,以及已经提交并存在于任务队列中的任务仍然会执行,但是不会接受任何新任务
*/
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess(); // 检查是否拥有权限关闭每个线程
advanceRunState(SHUTDOWN); // 将线程池的状态转换为SHUTDOWN
interruptIdleWorkers(); // 将池中的空闲线程全部中断
onShutdown(); // 主要用于ScheduledThreadPoolExecutor用于取消延迟的任务,其他类型线程池该方法无内容
} finally {
mainLock.unlock();
}
tryTerminate(); // 尝试将线程池状态转换为TERMINATED
}
shutdownNow()
/**
* 立即关闭线程池。池中所有的线程都会被中断,包括正在执行的线程,已经提交的任务不会处理,也不会接受任何新任务
*/
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess(); // 检查是否拥有权限关闭每个线程
advanceRunState(STOP); // 将线程池的状态转换为STOP
interruptWorkers(); // 中断所有线程
tasks = drainQueue(); // 排空任务队列,并返回任务列表
} finally {
mainLock.unlock();
}
tryTerminate(); // 尝试将线程池状态转换为TERMINATED
return tasks;
}
- drainQueue()方法排空任务队列,并返回任务列表:
private List<Runnable> drainQueue() {
BlockingQueue<Runnable> q = workQueue;
ArrayList<Runnable> taskList = new ArrayList<Runnable>();
q.drainTo(taskList); // 将任务队列中的任务全部移出到taskList中
if (!q.isEmpty()) { // 队列是DelayQueue或任何其他类型的队列,而poll或drainTo可能无法删除某些元素,则会将它们逐个删除,同时添加进入taskList
for (Runnable r : q.toArray(new Runnable[0])) {
if (q.remove(r))
taskList.add(r);
}
}
return taskList;
}
到此,Java线程池ThreadPoolExecutor源码解析终于结束。感谢阅读。