1 概述
通过上一篇《Java源码解读系列11—线程池(上,JDK1.8 )》的学习,对于线程池的使用应该问题不大。线程池源码非常多,本文主要讲解如何通过线程池复用线程,以及使用线程池创建线程跟直接调用Thread类的start方法启动线程这两者究竟有何异同。
2 线程池状态
将线程池状态存储在二进制的高位。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//32 - 3 = 29
private static final int COUNT_BITS = Integer.SIZE - 3;
//00011111 11111111 11111111 11111111
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
//11100000 00000000 00000000 00000000
private static final int RUNNING = -1 << COUNT_BITS;
//00000000 00000000 00000000 00000000
private static final int SHUTDOWN = 0 << COUNT_BITS;
//00100000 00000000 00000000 00000000
private static final int STOP = 1 << COUNT_BITS;
//01000000 00000000 00000000 00000000
private static final int TIDYING = 2 << COUNT_BITS;
//01100000 000000000 00000000 0000000
private static final int TERMINATED = 3 << COUNT_BITS;
//获取线程池得状态
// ~CAPACITY:11100000 00000000 00000000 00000000
// c 与~CAPACITY作与运算,因为~CAPACITY高三位为1,其他为0,因此与运算结果的高三位和c的高三位一样,其他位置为0
private static int runStateOf(int c) { return c & ~CAPACITY; }
//获取添加到worker中的线程数
//c的高三位代表线程池的状态
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
4 线程池的处理流程
public void execute(Runnable command) {
//非空校验
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//判断线程数是否小于核心线程数
if (workerCountOf(c) < corePoolSize) {
//添加到Worker
if (addWorker(command, true))
return;
c = ctl.get();
}
//判断线程池状态是否正在运行且线阻塞队列是否有容量存储新的线程
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
//再次检查线程池的运行状态,如果状态值大于等于SHUTDOWN,则将线程从阻塞队列中移除
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
//传入一个空线程,是为了添加一个Worker,从而获取阻塞队列中存储的线程
addWorker(null, false);
}
//如果添加woker失败,可能是线程池被关闭,也有可能是超过线程池中运行的最多线程数,因此使用拒绝策略
else if (!addWorker(command, false))
reject(command);
}
5 添加一个Worker
addWorker是用于启动线程,返回值为true表示启动一个新的线程去处理添加任务。
//workers提供给线程池监控,getPoolSize()中获取的线程数量就说workers的大小
private final HashSet<Worker> workers = new HashSet<Worker>();
//全局锁
private final ReentrantLock mainLock = new ReentrantLock()
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
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 (;;) {
//获取启动的线程数
int wc = workerCountOf(c);
//判断是否超过最大容量
if (wc >= CAPACITY ||
core为true,判断启动的线程数是否大于corePoolSize;
core为false,判断启动的线程数是否大于maximumPoolSize
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//通过CAS更新线程数量
if (compareAndIncrementWorkerCount(c))
//跳出当前for循环
break retry;
c = ctl.get(); // Re-read ctl
//如果状态被其他线程更新,则重新自旋
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
//标识线程是否已经启动
boolean workerStarted = false;
//标识线程是否被添加到workers中
boolean workerAdded = false;
Worker w = null;
try {
//new一个新的orker
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)) {
//校验新创建的Worker对象中包含的线程是否被启动
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//将新创建的worker添加到workers中
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
//largestPoolSize记录最大线程池大小
largestPoolSize = s;
//为true表示成功添加到workers中
workerAdded = true;
}
} finally {
//释放锁
mainLock.unlock();
}
//判断worker是否添加成功
if (workerAdded) {
//若是启动线程
//异步操作
t.start();
//更改workerStarted为true
workerStarted = true;
}
}
} finally {
//处理启动失败
if (! workerStarted)
addWorkerFailed(w);
}
//返回线程是否启动成功
return workerStarted;
}
6 Worker处理线程任务
6.1 构造函数
Worker(Runnable firstTask) {
//更新AQS的同步状态状态
setState(-1); // inhibit interrupts until runWorker
//添加的线程任务
this.firstTask = firstTask;
//new了一个线程,定义其属性
this.thread = getThreadFactory().newThread(this);
}
6.2 run方法
启动worker线程时候,调用run方法
public void run() {
runWorker(this);
}
final void runWorker(Worker w) {
//获取当前线程
Thread wt = Thread.currentThread();
//获取构造函数传入的线程
Runnable task = w.firstTask;
//清空firstTask
w.firstTask = null;
//释放锁
w.unlock(); // allow interrupts
//标识worker是不是因异常而中断
boolean completedAbruptly = true;
try {
//传入的任务不为空或者从阻塞队列获取的任务不为空
//阻塞队列获取不到任务是有可能导致当前线程发生阻塞,从而减少自旋
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
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
// 执行beforeExecute()钩子方法
//钩子方法预留了后续实现的逻辑
beforeExecute(wt, task);
Throwable thrown = null;
try {
//这一步是线程池的核心
//run方法是不会重新起一个线程,而是单纯调用task对象的run方法而已,从而实现线程池中线程的复用,不会因为构造方法传入task中的任务执行结束而结束
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()钩子方法
afterExecute(task, thrown);
}
} finally {
//清空任务
task = null;
//完成任务数加一
w.completedTasks++;
//释放锁
w.unlock();
}
}
//更新completedAbruptly状态,标识worker没有因异常而中断
completedAbruptly = false;
} finally {
//处理线程退出相关操作
processWorkerExit(w, completedAbruptly);
}
}
7 参考文献
1)JDK7在线文档
https://tool.oschina.net/apidocs/apidoc?api=jdk_7u4
2) JDK8在线文档
https://docs.oracle.com/javase/8/docs/api/
3) Bruce Eckel. Java编程思想,第4版,2007,机械工业出版社
4)方腾飞,魏鹏,程晓明. Java并发编程的艺术,第1版,2015年,机械工业出版社