携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
线程池原理介绍
1 首先分析下它的结构图
2 看下线程器构造器的参数如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
-
corePoolSize 代表核心线程数 不会被回收 正式员工
-
maximumPoolSize 最大线程数 -
keepAliveTime 线程回收时间 -
unit 时间单位 -
workQueue 阻塞队列 -
threadFactory 线程工厂 -
handler 拒绝策略
3 现在从向线程池中提交任务开始看起:
public void execute(Runnable command) {
// pan空
if (command == null)
throw new NullPointerException();
// 获取数值
int c = ctl.get();
// 低29位代表线程数
// 线程数小于核心线程数 直接创建worker
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
- 当前线程数小于核心线程数,正常提交任务.
- 当前线程数超过核心线程数,提交到队列中
- 队列已满,添加最大线程执行.
- 执行拒绝策略.
4 开始addWorker
// 添加worker core 代表时否为核心线程数
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 ||
wc >= (core ? corePoolSize : maximumPoolSize))
// 添加失败
return false;
// 增加线程数量
if (compareAndIncrementWorkerCount(c))
// 跳出循环
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;
boolean workerAdded = false;
Worker w = null;
try {
// 创建worker
w = new Worker(firstTask);
// 获取worker 对应的线程
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)) {
// Thread 已经调用了start方法 已经启动了 抛出异常
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
// 添加到set集合中
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
//worker 添加成功 启动线程
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
// worker 继承了AQS 实现Runnable接口
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
/**
* This class will never be serialized, but we provide a
* serialVersionUID to suppress a javac warning.
*/
private static final long serialVersionUID = 6138294804551838833L;
线程对象
/** Thread this worker is running in. Null if factory fails. */
final Thread thread;
/** Initial task to run. Possibly null. */
Runnable firstTask;
/** Per-thread task counter */
volatile long completedTasks;
/**
* Creates with given first task and thread from ThreadFactory.
* @param firstTask the first task (null if none)
*/
Worker(Runnable firstTask) {
// 初始状态为-1
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
// 创建线程 并将自己作为任务传递
this.thread = getThreadFactory().newThread(this);
}
/** Delegates main run loop to outer runWorker */
public void run() {
runWorker(this);
}
5 当worker对应的线程调用start 方法后 会调用worker 对应的run方法,
public void run() {
runWorker(this);
}
// 1 执行任务
final void runWorker(Worker w) {
// 获取当前线程
Thread wt = Thread.currentThread();
// 获取任务 在构造时进行初始化
Runnable task = w.firstTask;
w.firstTask = null;
// 设置state为0 最开始为-1
w.unlock(); // allow interrupts
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
// 判断线程是否已经中断 或者线程池已经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;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
// 当while循环结束时 需要回收线程
processWorkerExit(w, completedAbruptly);
}
}
// worker 中没有实现重入功能 因为在stop时会停止
protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
6 查看getTask() 做了什么 在前面的runworker中 会进行额外的线程回收
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
//判断状态
int rs = runStateOf(c);
// Check if queue empty only if necessary.
// 线程池状态结束
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
// 回收线程
decrementWorkerCount();
// 返回null 让调用的while循环结束
return null;
}
int wc = workerCountOf(c);
// Are workers subject to culling?
// 判断是否应该回收
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
// 减少线程数量
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
//阻塞式获取任务 若当前未达到核心线程数 take 超过核心线程数 poll 因为需要回收
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
6 回收worker
-- 回收线程
private void processWorkerExit(Worker w, boolean completedAbruptly) {
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
// 从getTask 返回null 此处不会进入 因为在getTask中已经decrement
decrementWorkerCount();
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 总任务数统计
completedTaskCount += w.completedTasks;
//删除worker
workers.remove(w);
} finally {
mainLock.unlock();
}
tryTerminate();
// 重新检查 线程池状态为停止 队列还存在任务没有消费,且线程数为0 需要在此添加
int c = ctl.get();
if (runStateLessThan(c, STOP)) {
if (!completedAbruptly) {
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
if (min == 0 && ! workQueue.isEmpty())
min = 1;
if (workerCountOf(c) >= min)
return; // replacement not needed
}
addWorker(null, false);
}
}
7 接着回到提交任务的下一步逻辑中
接着回到提交任务的下一步逻辑中
// 线程池运行状态 添加队列成功
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
// 重新check 线程池状态
if (! isRunning(recheck) && remove(command))
// 执行拒绝策略
reject(command);
// 线程数为0 但是刚提交任务 需要线程去消费
else if (workerCountOf(recheck) == 0)
// 创建worker 去消费
addWorker(null, false);
}
8 任务提交的最后一步逻辑
else if (!addWorker(command, false))
// 添加失败 执行拒绝策略
reject(command);
-
AbortPolicy 抛出RejectedExecutionException异常
-
DiscardOldestPolicy 移除队列中下一个要执行的任务,重新提交
-
CallerRunsPolicy 再当前提交的线程中执行
-
DiscardPolicy 静默丢弃 不抛出异常