JDK源码那些事儿之ThreadPoolExecutor
前面的文章中分析了Thread的源码,并介绍了其基本应用,然而在实际的企业级应用中执行任务的线程很少直接通过创建Thread,实现run方法的方式完成,通常是通过线程池的方式提交任务来更好的利用资源,进一步简化线程的使用,并防止线程资源的滥用。今天我们就一起来学习下ThreadPoolExecutor的源码,看一看jdK中线程池是如何创建和使用的
前言
JDK版本号:1.8.0_171
如果使用线程,我们通常都是使用线程池来进行操作,你可曾想过为什么?无非是效率,性能和资源多方面的考虑,笔者就不进行总结了,大家可以多思考下
在使用线程池时,我们通常都是通过Executors的工厂方法来得到的,当然,这些工厂方法最终基本上又是调用的ThreadPoolExecutor的构造器,可参考Executors的源码部分。不过阿里的java规范中也指出直接使用Executors方式可能会出现问题,还是直接通过ThreadPoolExecutor创建需要的线程池较好,之前在进行阻塞队列的源码学习时我也曾提到过线程池的使用,今天我们就看一看ThreadPoolExecutor的源码,学习下jdk中的线程池的实现原理
类定义
public class ThreadPoolExecutor extends AbstractExecutorService
Executor
我们先来看下Executor接口,我们可以看到,其中只定义了一个方法,入参为Runnable类,注释上也说明了这个类存在的意义,执行提交的Runnable任务的对象,在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行。这样在具体的实现中可以对Runnable任务提交与执行进行了解耦操作,我们只需要提交实现的Runnable任务即可,具体执行的部分交由Executor实现类完成,不需要关注其内部是如何实现的
public interface Executor {
void execute(Runnable command);
}
当然,注释部分也清楚的说明了同步还是异步(使用线程)执行由具体的Executor实现类决定。其中ExecutorService接口进一步进行了扩展,提供了Executor的管理相关方法(关闭Executor)和异步任务跟踪(Future),在AbstractExecutorService抽象类中实现了默认通用的方法,我们能看到submit方法提交的Runnable任务被封装成了FutureTask,以便完成任务的跟踪,具体不再多说,有兴趣可以自行研究
常量/变量
// control state,线程池控制状态标识,表示线程池的运行状态以及当前活动的线程,可参考后面的讲解
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// int值占32位,其中3位表示线程池运行状态,剩余部分表示活动的线程数,这里就表示其占用的位数
private static final int COUNT_BITS = Integer.SIZE - 3;
// 线程数最大值,最大能表示的数值
// 即二进制数值0001 1111 1111 1111 1111 1111 1111 1111
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
// 线程池运行状态
// 我们可以看到其左移的位数为COUNT_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 final BlockingQueue<Runnable> workQueue;
// 可重入锁
private final ReentrantLock mainLock = new ReentrantLock();
// 保存工作线程的集合,访问前必须获得mainLock锁
private final HashSet<Worker> workers = new HashSet<Worker>();
// 等待中断条件
private final Condition termination = mainLock.newCondition();
// 最大活动线程数
private int largestPoolSize;
// 任务完成总数
private long completedTaskCount;
// 线程工厂
private volatile ThreadFactory threadFactory;
// 拒绝策略
private volatile RejectedExecutionHandler handler;
// 空闲线程存活时间
private volatile long keepAliveTime;
// 是否允许核心线程超时
// 为true时使用keepAliveTime作为超时等待时间
// 为false时所有核心线程(包含空闲的)一直保持存活
private volatile boolean allowCoreThreadTimeOut;
// 核心线程数
// 当设置allowCoreThreadTimeOut为true时核心线程数最小为0
// 1.当任务提交时线程池中活动线程数还未达到设定的核心线程数,则直接创建核心线程执行提交的任务
// 2.当任务提交时线程池中活动线程数已达到设定的核心线程数,但还未达到最大线程数,则放入队列中进行等待处理或者队列满了之后直接创建线程处理
// 3.当任务提交时线程池中活动线程数已达到设定的最大线程数,则直接执行拒绝策略
private volatile int corePoolSize;
// 最大线程数,小于等于CAPACITY
private volatile int maximumPoolSize;
// 默认的拒绝策略,对拒绝的任务直接抛出异常
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
// 安全控制访问,简单了解就好,不是重点
private static final RuntimePermission shutdownPerm =
new RuntimePermission("modifyThread");
private final AccessControlContext acc;
这里对其中的ctl进行说明,初始化时值为:
(-1 << COUNT_BITS) | 0 = 1110 0000 0000 0000 0000 0000 0000 0000
此时前3位表示线程池处于RUNNING状态,后面29位表示线程池中当前活动的线程数为0,其他状态可参考下表理解
状态 | 二进制数值 |
---|---|
RUNNING | 1110 0000 0000 0000 0000 0000 0000 0000 |
SHUTDOWN | 0000 0000 0000 0000 0000 0000 0000 0000 |
STOP | 0010 0000 0000 0000 0000 0000 0000 0000 |
TIDYING | 0100 0000 0000 0000 0000 0000 0000 0000 |
TERMINATED | 0110 0000 0000 0000 0000 0000 0000 0000 |
同时线程池中的每种状态在注释部分也进行了解释,每种状态下对应的是什么状况还是需要稍微了解的,可参考下表理解:
状态 | 说明 |
---|---|
RUNNING | 接收新的任务并且处理已经提交到队列中的任务 |
SHUTDOWN | 不接收新的任务但是处理已经提交到队列中的任务 |
STOP | 不接收新的任务,也不处理已经提交到队列中的任务,同时中断已经在运行的任务 |
TIDYING | 终止所有任务,活动线程数workerCount被设置为0,触发线程的terminated方法执行 |
TERMINATED | terminated方法执行完毕 |
状态变化同样进行了说明,可参考下图了解:
构造方法
在重载的方法可以看到可以使用默认的线程工厂和默认的拒绝策略,最终都是调用下面这个方法
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;
}
内部类
接下来看下其内部类的实现,主要是Worker和拒绝策略
Worker
Worker继承了AQS,实现了Runnable接口,Worker是线程池中用于执行任务的线程。关于AQS的大名大家应该或多或少的有所了解,之后我也会分析其源码实现,这里大概理解即可,AQS定义了一套多线程访问共享资源的同步器框架,也就是解决多线程下对共享资源访问的相关问题,我们只要按照这个框架来实现使用即可,这里在线程池中很明显符合这种场景
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) {
// AQS状态设置为-1
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
public void run() {
// run方法执行任务,将当前的work传递过去
runWorker(this);
}
// 是否锁定
//
// 0代表未锁定状态
// 1代表锁定状态
protected boolean isHeldExclusively() {
return getState() != 0;
}
// 实现AQS的抽象方法,CAS尝试获取锁,将state状态置为1,成功则返回true,失败则返回false
protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 尝试释放锁,将state状态置为0
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) {
}
}
}
}
从上面我们可以看到最终是通过Worker中的线程执行其run方法中runWorker来完成任务的执行的,而runWorker是ThreadPoolExecutor的方法,将worker本身进行了传递,放到ThreadPoolExecutor.runWorker中进行处理
AbortPolicy
默认的拒绝策略实现,可以看到实现的接口方法rejectedExecution的说明,主要是对不能再接受任务时进行的相关处理,即线程池队列已满时对后续任务的处理。这个默认的处理我们也可以看到队列满了之后直接抛出RejectedExecutionException异常
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
CallerRunsPolicy
CallerRunsPolicy策略,在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务,当然这种情况下有可能会造成主线程的阻塞,慎用
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 会判断线程池状态是否正常
if (!e.isShutdown()) {
r.run();
}
}
}
DiscardPolicy
DiscardPolicy策略,会让被线程池拒绝的任务直接抛弃,不会抛异常也不会执行,从下面源码部分可以看出直接为空操作,什么也不做
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
DiscardOldestPolicy
DiscardOldestPolicy策略,当任务被拒绝添加时,会抛弃任务队列中最老的任务也就是最先加入队列的,再把这个新任务添加进去
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
// 出队最老的任务
e.getQueue().poll();
e.execute(r);
}
}
}
重要方法
runStateOf/workerCountOf/ctlOf
3个方法主要是用来计算线程池状态和活动线程数以及更新ctl的位运算操作,可参考上面的ctl的说明进行理解
// 当前线程池运行状态,取最高的3位作为运行状态
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; }
tryTerminate
尝试终止线程池,参考上面的线程池状态转换图,执行此方法前线程池状态处于SHUTDOWN或者STOP状态,可以参考其调用地方的源码,以下两种情况才能成功终止线程池,即对应上面的状态转换图
- 线程池为空,任务队列为空且处于SHUTDOWN状态
- 线程池为空且处于STOP状态
处于上述情况则线程池先转变为TIDYING,再转变为TERMINATED,与线程池状态转换图一致,参考理解
final void tryTerminate() {
// 循环自旋
for (;;) {
int c = ctl.get();
// 线程池处于RUNNING状态
// 或者TIDYING,TERMINATED状态(此时说明其他线程在执行tryTerminate)
// 或者SHUTDOWN状态且任务队列不为空时(还有未完成任务需要执行)
// 直接退出
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
// 活跃线程数非0,中断其中一个空闲线程worker
if (workerCountOf(c) != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
return;
}
// 先获取锁
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 将ctl状态置为TIDYING,且活动线程数置为0
// 这种状态下执行执行terminated,默认是空方法,子类可以进行重写
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
terminated();
} finally {
// 最终将ctl状态置为TERMINATED
ctl.set(ctlOf(TERMINATED, 0));
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
execute
执行提交的任务,提交任务submit方法最终也是调用的该方法进行任务的执行的。此方法会在活动线程数超过核心线程数corePoolSize时将任务放在任务队列中等待空闲线程拿到任务去执行
public void execute(Runnable command) {
// 任务非空
if (command == null)
throw new NullPointerException();
int c = ctl.get();
// 活动线程数小于核心线程数
if (workerCountOf(c) < corePoolSize) {
// 添加新的线程执行任务
// 参数为true表示活动线程数不能超过核心线程数
if (addWorker(command, true))
return;
// 再次获取ctl
c = ctl.get();
}
// 执行到这里表示活动的线程数大于等于核心线程数
// 上面添加worker未成功
// 线程池处于运行状态,则将任务尝试放入任务队列等待
if (isRunning(c) && workQueue.offer(command)) {
// 再次获取ctl
int recheck = ctl.get();
// 如果线程池不在RUNNING状态,则需要将任务从队列中移除
// 同时执行拒绝策略拒绝任务
if (! isRunning(recheck) && remove(command))
reject(command);
// 执行到此处分支判断活动线程数为0
// 添加新的空任务worker,唤醒等待中的队列任务去执行
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 执行到这个分支表示线程池状态非RUNNING状态或者任务队列已满
// 尝试添加worker
else if (!addWorker(command, false))
// 未添加成功则执行拒绝策略
reject(command);
}
addWorker
addWorker创建新的线程worker执行任务,core为true时表示不能超过核心线程数,false则表示不能超过最大线程数
当满足下列任一情况时,不再添加线程任务,即返回false,添加任务失败:
- 当前线程池处于STOP,TIDYING,TERMINATED状态时
- 当前线程池处于SHUTDOWN状态时,任务非空
- 当前线程池处于SHUTDOWN状态时,任务为空,任务队列为空
这里是因为线程池状态为SHUTDOWN时,不再允许添加新的任务,但是会执行已在任务队列中的任务,具体可参考runWorker方法,addWorker创建完新的worker后会启动线程,如果任务为空则会从任务队列中获取任务来执行
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
// 获取ctl
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;
// CAS更新ctl
if (compareAndIncrementWorkerCount(c))
// 成功直接跳出循环
break retry;
// 失败则重新获取ctl
c = ctl.get(); // Re-read ctl
// 验证运行状态,与之前不同则重新跳出继续循环,否则在这个内部继续循环
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
// 到此,表明已经成功更新ctl值加1,下面是添加构造的Worker的部分了
// worker增加是否启动标识
boolean workerStarted = false;
// worker增加是否成功标识
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 {
int rs = runStateOf(ctl.get());
// 线程池为RUNNING状态
// 或者线程池为SHUTDOWN状态并且任务为空
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
// worker中的线程被启动则抛出异常
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
// 添加worker
workers.add(w);
// 获取当前workers的数量
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
// 启动worker线程
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
// 任务启动失败,删除回滚
addWorkerFailed(w);
}
return workerStarted;
}
getTask
从队列中获取任务,在获取任务前需要先进行一些处理
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.
// 线程池状态为STOP,TIDYING,TERMINATED
// 或者线程池状态为SHUTDOWN且任务队列为空
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
// 活跃线程数递减
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
// Are workers subject to culling?
// 当线程池设置超时等待获取任务或者活跃线程数大于核心线程数
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
// 活跃线程数大于最大线程数并且活跃线程数大于1或任务队列为空
// 超时并且活跃线程数大于1或任务队列为空
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
// 递减活跃线程数
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
// 从任务队列获取任务
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
runWorker
执行任务核心方法,先执行提交的worker中的任务firstTask,如果firstTask为null则会去任务队列中获取任务来执行,且当任务执行后,会再去队列中取任务来执行
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
// 将worker中的firstTask置为null
w.firstTask = null;
// 允许被中断
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,TIDYING,TERMINATED
// 或线程池为STOP,TIDYING,TERMINATED且当前线程已中断
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 {
// 和beforeExecute同样作用
afterExecute(task, thrown);
}
} finally {
// 执行完毕后将任务置null,方便后续任务队列中任务的执行
task = null;
// 完成任务数递增
w.completedTasks++;
w.unlock();
}
}
// 所有任务执行完毕设置标志
completedAbruptly = false;
} finally {
// 后续处理
processWorkerExit(w, completedAbruptly);
}
}
processWorkerExit
runWorker中被调用,最终任务执行完毕或者被中断时退出前进行必要的后续处理,比如更新完成的任务数量,在核心线程数较小时开启新的线程来处理任务队列中的任务
private void processWorkerExit(Worker w, boolean completedAbruptly) {
// 工作线程被中断时处理,活动线程递减
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount();
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 完成任务的数量
completedTaskCount += w.completedTasks;
// 从workers集合中移除入参的worker
workers.remove(w);
} finally {
mainLock.unlock();
}
// 尝试终止
tryTerminate();
// 获取ctl
int c = ctl.get();
// 线程池状态处于RUNNING或SHUTDOWN
if (runStateLessThan(c, STOP)) {
if (!completedAbruptly) {
// 任务正常执行完毕才会进入这里
// 设置了allowCoreThreadTimeOut则最小值为0否则为corePoolSize
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
// min为0且任务队列非空,说明还有任务需要继续执行
if (min == 0 && ! workQueue.isEmpty())
min = 1;
// 活动的线程数大于等于min
if (workerCountOf(c) >= min)
// 不需要创建新的worker继续执行任务了,复用这些已经创建的线程即可
return; // replacement not needed
}
// 增加新的null任务worker来执行剩余的任务
addWorker(null, false);
}
}
shutdown
参考线程池状态说明,和上面说明的SHUTDOWN状态一样,也就是不再接收新任务,但是还是会处理任务队列中的任务,并且不会中断已在执行中的任务线程
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
// 更新线程池状态为SHUTDOWN
advanceRunState(SHUTDOWN);
// 中断空闲worker
interruptIdleWorkers();
// shutdown钩子函数,空方法,可被子类实现
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
// 尝试终止线程池
tryTerminate();
}
shutdownNow
方法同shutdown类似,不再接收新任务,并且会清除任务队列中的任务,会中断所有任务线程包括已在执行任务的线程
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
// 更新线程池状态为STOP
advanceRunState(STOP);
// 中断worker
interruptWorkers();
// 清除队列任务,并将队列任务集合拷贝出来
tasks = drainQueue();
} finally {
mainLock.unlock();
}
// 尝试终止线程池
tryTerminate();
return tasks;
}
interruptWorkers
中断所有线程workers
private void interruptWorkers() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
w.interruptIfStarted();
} finally {
mainLock.unlock();
}
}
interruptIdleWorkers
中断所有空闲线程workers,使用入参onlyOne判断是否只中断一个空闲线程,无入参默认false,中断全部空闲线程workers
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
private void interruptIdleWorkers() {
interruptIdleWorkers(false);
}
总结
本文通过ThreadPoolExecutor的源码来介绍了jdk中线程池的实现原理,说明了线程池状态之间的转换,我们可以了解到很多线程池实现的机制,帮助我们在实际的开发中更好的使用,另外,需要注意的是,尽量还是直接使用ThreadPoolExecutor的构造方法来使用线程池而不是使用Executors的工厂方法,其中的弊端可参考阿里的java规范,主要是默认的设置可能会造成一些问题
以上内容如有问题欢迎指出,笔者验证后将及时修正,谢谢