为何使用线程池技术
1.线程是重量级资源,线程创建、销毁需要耗费较大的性能,因此重复使用线程能极大地改善程序性能。
2.线程并不是越多越好,线程数量和性能呈抛物线关系,而且通过new Thread方式创建的线程无法很好地进行管控。
3.new Thread方式创建的线程不利于扩展,比如定时、定期执行任务,线程中断。
线程池如何提升性能
主要是避免了线程的创建、销毁这部分时间的耗费
1.普通线程执行某项任务
创建线程耗费T1时间,真正执行耗费T2时间,销毁线程耗费T3时间,执行该项任务时间总和T=T1+T2+T3
2.线程池执行某项任务
使用的线程从池里获取,T1+T3的时间基本忽略不计,执行该项任务时间总和T=T2
线程池工作流程
1.如果当前woker数量小于corePoolSize,则新建一个woker并把当前任务分配给该woker线程,成功则返回
2.如果第一步失败,则尝试把任务放入阻塞队列,如果成功则返回
3.如果第二步失败,则判断如果当前woker数量小于maximumPoolSize,则新建一个woker并把当前任务分配给该woker线程,成功则返回
4.如果第三步失败,则调用拒绝策略处理该任务
线程池基本要素
任务列队:用来缓存提交的任务
工作线程队列:一个线程池要想很好地管理和控制线程数量,可以通过后面的两个参数实现,线程池需要维护的核心数量corePoolSize,线程池自动扩充线程时最大的数量:maximumPoolSize
任务拒绝策略:如果线程数量已达上限并且任务队列也满了,就需要相应的拒绝策略来告诉提交任务的人
线程工厂:用于创建线程的,按需定制线程,执行我们的提交的任务
以上是线程池相关的基础知识,下面介绍JDK线程池的实现原理
Executor是一个强大且非常灵活的异步执行框架,它以Runnable为任务对象,并且提供了一套将任务提交和任务执行分离开来的机制,让提交任务的过程和执行任务的过程得到充分的解耦。Executor还提供了对线程池生命周期的管理,以及统计信息收集,和应用程序管理机制和性能监控,以及任务调度功能。
Executor继承关系图
Executor接口只有一个方法void execute(Runnable command);
ExecutorService接口源码
public interface ExecutorService extends Executor {
// 该两方法用于ExecutorService的关闭,关闭后拒绝接受新任务
void shutdown(); // 允许先前提交的任务在线程池终止之前执行
List<Runnable> shutdownNow(); // 会阻止开启新的任务并且尝试停止当前正在执行的任务
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
// submit扩展了execute方法,返回future对象,future主要用于启动取消异步任务,查询异步任务执行情况以及获取异步任务的执行结果,future源码分析见FutureTask章节
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
// 以下三个方法invokeXXX以批量形式执行一组任务,然后等待至少一个或者全部的任务完成
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit) throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
AbstractExecutorService抽象类源码
AbstractExecutorService类提供了ExecutorService接口部分方法的默认实现,这个类使用了newTaskFor()方法返回的RunnableFuture对象实现了submit(),invokeAny()和invokeAll()方法
public abstract class AbstractExecutorService implements ExecutorService {
//通过runnable和一个value参数,创建一个FutureTask
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
//通过一个callable创建一个FutureTask
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
//通过Future#get()获取出来的值,永远都为null
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
//通过Future#get()获取出来的值为result。
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
//通过Future#get()获取出来的值为任务执行的结果。
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
//如果任务集后为空,则抛出一个NullPointerException
if (tasks == null)
throw new NullPointerException();
//创建一个和任务数量等大的ArrayList.
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
//标志任务是否完成
boolean done = false;
try {
//将tasks里面的每个Callable转化成Future,添加到futures里面,并交给Executor#execute()方法执行
for (Callable<T> t : tasks) {
RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
execute(f);
}
//判断futures里面的Future是否执行结束,如果还没有完成,通过get()阻塞直到任务完成
//也是就说执行完这一段代码,futures里面的每一个任务都是执行完成的情况
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
try {
f.get();
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
}
}
}
done = true;
//返回ArrayList
return futures;
} finally {
if (!done)//如果任务没有完成的,就全部都取消,并释放内存
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);//采用中断线程的方式取消任务
}
}
// 超时版本
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit) throws InterruptedException {
//如果任务集后为空,则抛出一个NullPointerException
if (tasks == null)
throw new NullPointerException();
//将超时时间转化成纳秒
long nanos = unit.toNanos(timeout);
//创建一个和任务数量等大的ArrayList.
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
//标志任务是否完成
boolean done = false;
try {
//将tasks里面的每个Callable转化成Future,添加到futures里面
for (Callable<T> t : tasks)
futures.add(newTaskFor(t));
//超时时间点
final long deadline = System.nanoTime() + nanos;
//记录一下futures的大小,
final int size = futures.size();
//执行任务,如果超时就直接返回futures
for (int i = 0; i < size; i++) {
execute((Runnable)futures.get(i));
nanos = deadline - System.nanoTime();
if (nanos <= 0L)
return futures;
}
//判断futures里面的Future是否执行结束,如果还没有完成,通过get()阻塞直到任务完成
//也是就说执行完这一段代码,要么futures里面的每一个任务都是执行完成了,要么就是超时了
for (int i = 0; i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
if (nanos <= 0L)
return futures;
try {
//这里捕捉了get()方法可能出现了所有的异常
f.get(nanos, TimeUnit.NANOSECONDS);
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
} catch (TimeoutException toe) {
return futures;
}
nanos = deadline - System.nanoTime();
}
}
//标记任务完成
done = true;
return futures;
} finally {
if (!done)//如果任务没有完成的,就全部都取消,并释放内存
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);//采用中断线程的方式取消任务
}
}
}
ThreadPoolExecutor线程池(核心)
先介绍ThreadPoolExecutor成员变量,为后续阅读源码打个基础
public class ThreadPoolExecutor extends AbstractExecutorService {
// 默认为false,用于控制核心线程在空闲状态是否会被回收
private volatile boolean allowCoreThreadTimeOut;
// 存活的时间,当非核心线程闲置的时间超过它时,将会被回收
private volatile long keepAliveTime;
// 核心线程的数量,默认情况下即使核心线程处于空闲状态也不会被回收,
// 除非把allowCoreThreadTimeOut设置为true
private volatile int corePoolSize;
// 存放任务的队列,如果当前线程数 > 核心线程数,新提交的任务将会被放入到该任务对列
// 它是一个阻塞队列,通常有SynchronousQueue(直接提交),LinkedBlockingQueue(无界队列), ArrayBlockingQueue (有界队列)三种
private final BlockingQueue<Runnable> workQueue;
// 线程池能容纳最大的线程数
private volatile int maximumPoolSize;
// 创建新线程使用的线程工厂
private volatile ThreadFactory threadFactory;
// 当任务队列满并且当前线程等于线程池能容纳的最大线程数时所采用的拒绝策略
private volatile RejectedExecutionHandler handler;
// 1.AbortPolicy:直接抛出异常,默认策略
// 2.CallerRunsPolicy:用调用者所在的线程来执行任务
// 3.DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务
// 4.DiscardPolicy:直接丢弃任务
// 用户也可以通过RejectedExecutionHandler接口进行自定义饱和策略
// 默认的拒绝策略
private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
// 统计线程池完成的任务数量
private long completedTaskCount;
// 工作线程池,存放工作线程的地方,Worker包含一个线程和对应的任务
private final HashSet<Worker> workers = new HashSet<Worker>();
// 用于记录最大的工作线程池的工作线程的大小.
private int largestPoolSize;
}
线程池状态和线程数量表现方法
// ctl是控制线程的状态的,里面包含两个状态,线程的数量和线程池运行的状态
// 它是一AtomicInteger类型,由后面的操作可以得知,
// 高3位是用来保存线程池运行的状态的,低29位用于保存线程的数量,这里的限制是2^29-1,大约有5亿3千6百万左右。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// COUNT_BITS =29,用于位于操作
private static final int COUNT_BITS = Integer.SIZE - 3;
// 2^29-1 =536,870,911 线程的容量,二进制表示: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
// 高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:所有任务都已经完成,线程数都被回收,线程会转到TIDYING状态会继续执行钩子方法
private static final int TIDYING = 2 << COUNT_BITS;
// 高3位:110:钩子方法执行完毕
private static final int TERMINATED = 3 << COUNT_BITS;
// 用于打包ctl或者拆包ctl的,如果你源码看得比较多,这种操作应该是经常看到的
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; }
线程池五种状态转化
Running、ShutDown、Stop、Tidying、Terminated
RUNNING
状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理
状态转化:线程池初始状态是RUNNING,换句话说线程池一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
SHUTDOWN
状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务
状态转换:调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN
STOP
状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务
状态转换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP
TIDYING
状态说明:当所有的任务已终止,ctl记录的任务数量为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现
状态转换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。 当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING
TERMINATED
状态说明:线程池彻底终止,就变成TERMINATED状态
状态转换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED
ThreadPoolExecutor构造方法及参数
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;
}
接下来分析execute()方法
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
// 获取线程池控制状态
int c = ctl.get();
// 工作线程数小于核心线程数,创建一个工作线程来运行任务,成功则直接结束
if (workerCountOf(c) < corePoolSize) {
// addWorker第二个参数表示限制添加线程的数量是根据corePoolSize来判断还是maximumPoolSize来判断:true根据corePoolSize来判断,false根据maximumPoolSize来判断
if (addWorker(command, true))
return;
// 创建工作线程失败则再次获取线程池控制状态
c = ctl.get();
}
// 如果线程池处于RUNNING状态,则尝试把任务添加到任务队列
if (isRunning(c) && workQueue.offer(command)) {
// 再次获取线程池控制状态
int recheck = ctl.get();
// 如果线程池已经不是RUNNING状态了(可能已被关闭),把任务从队列中移除,并执行拒绝任务策略
if (!isRunning(recheck) && remove(command))
reject(command);
// 如果工作线程数为0(旧线程可能已被回收),则创建一个新的工作线程
else if (workerCountOf(recheck) == 0)
// 此处传null,因为前面已将任务放入队列
addWorker(null, false);
}
// 执行到这里存在两种情况
// 1.线程池已经不是RUNNING状态
// 2.线程池是RUNNING状态,但workerCount >= corePoolSize并且workQueue已满
else if (!addWorker(command, false))
reject(command);
}
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
// 获取线程池的控制状态
int c = ctl.get();
// 获取线程池的运行状态
int rs = runStateOf(c);
// 线程池状态为RUNNING则放行
// 线程池状态为SHUTDOWN,任务为null,任务队列不为空则放行,即线程池的状态SHUTDOWN时,它不接收新任务,但是会继续运行任务队列中的任务
// 其它状态均拦截
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
// 获取工作线程数
int wc = workerCountOf(c);
// 工作线程数 >= 最大容量
// 据据core来控制工作线程数量是 >= corePoolSize 还是 >= maximumPoolSize
if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize))
return false;
// 原子性增加工作线程数(+1)成功,跳出外层循环
if (compareAndIncrementWorkerCount(c))
break retry;
// 否则再次获取线程池控制状态
c = ctl.get();
// 如果线程池的状态发生改变了,再次重复外层循环
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
// 工作线程开始标记符
boolean workerStarted = false;
// 工作线程被添加标记符
boolean workerAdded = false;
// Worker包装了线程和任务
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());
// 线程池状态为RUNNING或(线程池状态SHUTDOWN并且提交的任务为null)
if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) {
// 如果线程已运行或还未死掉,抛出IllegalThreadStateException异常
if (t.isAlive())
throw new IllegalThreadStateException();
// 将worker添加到工作线程Set里
workers.add(w);
int s = workers.size();
// 如果工作线程池的大小大于largestPoolSize
if (s > largestPoolSize)
// 置largestPoolSize为工作线程池最大值
largestPoolSize = s;
// 置工作线程被添加标记符为true
workerAdded = true;
}
} finally {
mainLock.unlock();
}
// 如果工作线程已经被添加到工作线程池了
if (workerAdded) {
t.start();
// 置工作线程开始标记符为true
workerStarted = true;
}
}
} finally {
// 如果没有添加,那么移除任务,并减少工作线程的数量(-1)
if (!workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
// 该run是Worker类中的一个方法
public void run() {
runWorker(this);
}
// runWorker该方法真正执行任务
final void runWorker(Worker w) {
// 获取当前线程(与worker绑定)
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock();
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
// 任务不为空或队列中还有任务
w.lock();
// 如果线程池正在停止,要保证当前线程是中断状态,如不是,则要保证当前线程不是中断状态。
// 可能在执行if语句期间也执行了shutdownNow方法,shutdownNow方法会把线程池状态设置为STOP,回顾一下STOP状态:不能接受新任务,也不处理队列中的任务,会中断正在处理任务的线程。
// 在线程池处于RUNNING或SHUTDOWN状态时,调用shutdownNow()方法会使线程池进入到该状态,STOP状态要中断线程池中的所有线程,而这里使用Thread.interrupted()来判断是否中断是为了确保在RUNNING或SHUTDOWN状态时线程是非中断状态的,因为Thread.interrupted()方法会复位中断的状态
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;
// 任务完成数加1
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
// 当所有任务完成之后的钩子方法调用
processWorkerExit(w, completedAbruptly);
}
}
private Runnable getTask() {
// 表示上次从阻塞队列中获取任务时是否超时
boolean timedOut = false;
for (;;) {
// 获取线程池的控制状态
int c = ctl.get();
// 获取线程池的运行状态
int rs = runStateOf(c);
// 线程池状态 >= STOP或者任务队列为空
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
// 工作线程数减1
decrementWorkerCount();
return null;
}
// 获取工作线程数
int wc = workerCountOf(c);
// 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭
// 当设置allowCoreThreadTimeOut(false)时,工作线程数大于核心线程数部分线程超时关闭
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
// wc > maximumPoolSize的情况是因为可能在此方法执行阶段同时执行了setMaximumPoolSize方法
// timed && timedOut 如果为true,表示当前操作需要进行超时控制,并且上次从阻塞队列中获取任务发生了超时
// 如果有效线程数量大于1,或者阻塞队列是空的,那么尝试将workerCount减1,如果减1失败,则重试
// wc = 1说明当前线程是线程池中唯一的线程了
if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
// poll方法有限时间等待获取任务,不阻塞,
// take方法会无限时间等待,直到队列任务不为空
Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();
// 如果获取到的任务不为null,直接返回任务
if (r != null)
return r;
// 等待指定时间后,还是获取不到任务,说明任务队列为空了,则置超时标识为true
timedOut = true;
} catch (InterruptedException retry) {
// 如果被中断了,将超时标识置为false
timedOut = false;
}
}
}
线程池的终止
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 判断调用者是否有权限shutdown线程池
checkShutdownAccess();
// CAS+循环设置线程池状态为shutdown
advanceRunState(SHUTDOWN);
// 中断所有空闲线程
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
}
finally {
mainLock.unlock();
}
// 尝试终止线程池
tryTerminate();
}
final void tryTerminate() {
for (;;) {
int c = ctl.get();
/**
* 线程池是否需要终止
* 如果以下3中情况任一为true,return,不进行终止
* 1、还在运行状态
* 2、状态是TIDYING、或 TERMINATED,已经终止过了
* 3、SHUTDOWN且workQueue不为空
*/
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
/**
* 只有shutdown状态且workQueue为空,或者stop状态能执行到这一步
* 如果此时线程池还有线程(正在运行任务,正在等待任务)
* 中断唤醒一个正在等任务的空闲worker
* 唤醒后再次判断线程池状态,会return null,进入processWorkerExit()流程
*/
if (workerCountOf(c) != 0) {
// 中断workers集合中的空闲任务,参数为true,只中断一个
interruptIdleWorkers(ONLY_ONE);
return;
}
// 如果状态是SHUTDOWN,workQueue也为空了,正在运行的worker也没有了,开始terminated
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// CAS:将线程池的ctl变成TIDYING(所有的任务被终止,workCount为0,为此状态时将会调用terminated()方法),期间ctl有变化就会失败,会再次for循环
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
terminated(); // 交由子类实现
}
finally {
// 将线程池的ctl变成TERMINATED
ctl.set(ctlOf(TERMINATED, 0));
// 唤醒调用了等待线程池终止的线程 awaitTermination()
termination.signalAll();
}
return;
}
}
finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
private void interruptIdleWorkers() {
interruptIdleWorkers(false);
}
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
// 此处加锁,workers是HashSet类型的,不能保证线程安全
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();
}
}
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
// 中断所有工作线程,无论是否空闲
interruptWorkers();
// 取出队列中没有被执行的任务
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}