ThreadPoolExecutor
源码剖析:
- 存在包:
package java.util.concurrent;
- 继承关系:
public class ThreadPoolExecutor extends AbstractExecutorService
- 基本属性:
重要属性列举:
/*
* The main pool control state, ctl, is an atomic integer packing
* two conceptual fields
* workerCount, indicating the effective number of threads
* runState, indicating whether running, shutting down etc
* ctl是线程池的控制状态,是AtomicInteger类型的,里面包含两部分,
* workcount---线程的数量,runState---线程池的运行状态。
* 这里限制了最大线程数是2^29-1,大约500百万个线程,这也是个问题,所以ctl也可以变成
AtomicLong类型的。
*/
//记录线程池状态和线程数量(总共32位,前三位表示线程池状态,后29位表示线程数量)
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//线程数量统计位数29 Integer.SIZE=32
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 (左移两位乘2的n次方)
//运行中 :接受新任务并且继续处理阻塞队列中的任务
private static final int RUNNING = -1 << COUNT_BITS;
//关闭 :不接受新任务但是会继续处理阻塞队列中的任务
private static final int SHUTDOWN = 0 << COUNT_BITS;
//停止 :不接受新任务,不在执行阻塞队列中的任务,中断正在执行的任务
private static final int STOP = 1 << COUNT_BITS;
//整理 :所有任务都已经完成,线程数都被回收,线程会转到TIDYING状态会继续执行钩子方法,所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为0,将要调用terminated方法
private static final int TIDYING = 2 << COUNT_BITS;
//终止 :钩子方法执行完毕,terminated方法调用完成以后的状态
private static final int TERMINATED = 3 << COUNT_BITS;
//获取运行状态(获取前3位)(取反 相与)
private static int runStateOf(int c) { return c & ~CAPACITY; }
//获取线程个数(获取后29位)
private static int workerCountOf(int c) { return c & CAPACITY; }、
private static int ctlOf(int rs, int wc) { return rs | wc; }
存放线程的阻塞队列
private final BlockingQueue<Runnable> workQueue;
重入锁
private final ReentrantLock mainLock = new ReentrantLock();
存放工作线程的集合
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;
空闲的时候让线程等待keepAliveTime,timeout后使得poolSize能够降为0
private volatile boolean allowCoreThreadTimeOut;
核心线程数, 线程池维护线程的最少数量
private volatile int corePoolSize;
最大线程数
private volatile int maximumPoolSize;
默认线程池拒绝任务的处理类
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
private static final RuntimePermission shutdownPerm =
new RuntimePermission("modifyThread");
- 线程池状态转换:
RUNNING -> SHUTDOWN
显式调用shutdown()方法, 或者隐式调用了finalize()方法
(RUNNING or SHUTDOWN) -> STOP
显式调用shutdownNow()方法
SHUTDOWN -> TIDYING
当线程池和任务队列都为空的时候
STOP -> TIDYING
当线程池为空的时候
TIDYING -> TERMINATED
当 terminated() hook 方法执行完成时候
- ThreadPoolExecutor构造方法:
重要的构造参数:
//构造参数及使用时间:
int corePoolSize:核心线程数;默认情况下,在创建了线程池后,线程池中的线程数为0,当提交一个任务时,线程池创建一个新线程执行任务,,直到当前线程数等于corePoolSize;
如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;
如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。
int maximumPoolSize:最大线程数,即线程池中允许存在的最大线程数;如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize。
long keepAliveTime:线程存活时间,对于超过核心线程数的线程,当线程处理空闲状态下,且维持时间达到keepAliveTime时,线程将被销毁;。默认情况下,在当前线程数量workCount>核心线程数corePoolSize时使用。
TimeUnit unit:keepAliveTime的时间单位;静态属性 SECONDS;
TimeUnit.DAYS; //天
TimeUnit.HOURS; //小时
TimeUnit.MINUTES; //分钟
TimeUnit.SECONDS; //秒
TimeUnit.MILLISECONDS; //毫秒
TimeUnit.MICROSECONDS; //微妙
TimeUnit.NANOSECONDS; //纳秒
BlockingQueue<Runnable> workQueue:一个阻塞队列,用来存储等待执行的任务;
核心线程数corePoolSize <= 当前线程数量workCount <= 最大线程数maximumPoolSize,即超过核心线程数后,存到工作队列中;
阻塞队列有4种:
(1)ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原则对元素进行排序。
(2)LinkedBlockingQueue:一个基于链表结构的无界阻塞队列,此队列按FIFO排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。
(3)SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于Linked-BlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。不排队,直接提交。
(4)PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
RejectedExecutionHandler handler:当到达线程数max上限或工作队列已满时的拒绝处理逻辑;
线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务,线程池提供了4种策略:
(1)ThreadPoolExecutor.AbortPolicy:默认策略,丢弃任务并抛出RejectedExecutionException异常。
(2)ThreadPoolExecutor.DiscardPolicy:直接丢弃任务,但是不抛出异常。
(3)ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行当前任务(重复此过程)。
(4)ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务。
ThreadFactory threadFactory:创建线程的工厂,用于标记区分不同线程池所创建出来的线程;通过自定义的线程工厂可以给每个新建的线程设置一个具有识别度的线程名,设置优先级,守护线程。
Executors静态工厂里默认的threadFactory,线程的命名规则是“pool-数字-thread-数字”
4个构造方法
//用给定的初始参数和默认的线程工厂及被拒绝的执行处理程序创建新的 ThreadPoolExecutor。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
//用给定的初始参数和默认被拒绝的执行处理程序创建新的 ThreadPoolExecutor。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
//用给定的初始参数和默认的线程工厂创建新的 ThreadPoolExecutor。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
// 用给定的初始参数创建新的 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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
- 嵌套类:
4种拒绝策略:
//用于被拒绝任务的处理程序,它直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务。
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
/**
* Executes task r in the caller's thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
/**
* A handler for rejected tasks that throws a
* {@code RejectedExecutionException}.
*/
//用于被拒绝任务的处理程序,它将抛出 RejectedExecutionException.
//线程数达到上限,直接抛出异常,默认情况下采用这种策略
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always.
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
/**
* A handler for rejected tasks that silently discards the
* rejected task.
*/
//用于被拒绝任务的处理程序,它放弃最旧的未处理请求,然后重试 execute;如果执行程序已关闭,则会丢弃该任务。
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
/**
* A handler for rejected tasks that discards the oldest unhandled
* request and then retries {@code execute}, unless the executor
* is shut down, in which case the task is discarded.
*/
//不处理,丢弃掉
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
public DiscardOldestPolicy() { }
/**
* Obtains and ignores the next task that the executor
* would otherwise execute, if one is immediately available,
* and then retries execution of task r, unless the executor
* is shut down, in which case task r is instead discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
}
- 方法介绍:
void execute(Runnable command):执行给定任务。
void shutdown():按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。
List<Runnable> shutdownNow():尝试停止所有的活动执行任务、暂停等待任务的处理,并返回等待执行的任务列表。
boolean isShutdown():如果此执行程序已关闭,则返回 true。
boolean isTerminated():如果关闭后所有任务都已完成,则返回 true。判断线程池中的任务是否全部完成。全部完成返回true,否则返回false
boolean isTerminating():如果此执行程序处于在 shutdown 或 shutdownNow 之后正在终止但尚未完全终止的过程中,则返回 true。
boolean awaitTermination(long timeout, TimeUnit unit):请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行。
protected void finalize():当不再引用此执行程序时,调用 shutdown。
void setThreadFactory(ThreadFactory threadFactory):设置用于创建新线程的线程工厂。
ThreadFactory getThreadFactory():返回用于创建新线程的线程工厂。
void setRejectedExecutionHandler(RejectedExecutionHandler handler):设置用于未执行任务的新处理程序。
RejectedExecutionHandler getRejectedExecutionHandler():返回用于未执行任务的当前处理程序。
void setCorePoolSize(int corePoolSize):设置核心线程数。
int getCorePoolSize():返回核心线程数。
int prestartAllCoreThreads():启动所有核心线程,使其处于等待工作的空闲状态。
boolean prestartCoreThread():启动核心线程,使其处于等待工作的空闲状态。
void allowCoreThreadTimeOut(boolean value):如果在保持活动时间内没有任务到达,新任务到达时正在替换(如果需要),则设置控制核心线程是超时还是终止的策略。
boolean allowsCoreThreadTimeOut():如果此池允许核心线程超时和终止,如果在 keepAlive 时间内没有任务到达,新任务到达时正在替换(如果需要),则返回 true。
void setMaximumPoolSize(int maximumPoolSize):设置允许的最大线程数。
void getMaximumPoolSize():返回设置的最大线程数。
void setKeepAliveTime(long time, TimeUnit unit):设置线程在终止前可以保持空闲的时间限制。
long getKeepAliveTime(TimeUnit unit):返回线程保持活动的时间,该时间就是超过核心池大小的线程可以在终止前保持空闲的时间值。(unit 单位)
BlockingQueue<Runnable> getQueue():返回此执行程序使用的任务队列。
boolean remove(Runnable task):从执行程序的内部队列中移除此任务(如果存在),从而如果尚未开始,则其不再运行。
void purge():尝试从工作队列移除所有已取消的 Future 任务。
int getPoolSize():返回池中的当前线程数。
int getActiveCount():返回主动执行任务的近似线程数。
int getLargestPoolSize():返回曾经同时位于池中的最大线程数。
int getMaximumPoolSize():返回允许的最大线程数。
long getTaskCount(): 返回曾计划执行的近似任务总数。
long getCompletedTaskCount(): 返回已完成执行的近似任务总数。
protected void beforeExecute(Thread t, Runnable r):在执行给定线程中的给定 Runnable 之前调用的方法。
protected void afterExecute(Runnable r, Throwable t) :基于完成执行给定 Runnable 所调用的方法。
protected void terminated():当 Executor 已经终止时调用的方法。
-
重要方法简析:
(1)execute()方法:
分为三步:
1.判断输入的请求不能为null,否则抛出空指针异常;
2.获取当前请求线程的数量,
3.* 如果正在运行的线程数小于corePoolSize,那么将调用addWorker 方法来创建一个新的线程,并将该任务作为新线程的第一个任务来执行。
当然,在创建线程之前会做原子性质的检查,如果条件不允许,则不创建线程来执行任务,并返回false.
* 如果一个任务成功进入阻塞队列,
那么我们需要进行一个双重检查来确保是我们已经添加一个线程(因为存在着一些线程在上次检查后他已经死亡)或者当我们进入该方法时,该线程池已经关闭。
所以,我们将重新检查状态,线程池关闭的情况下则回滚入队列,线程池没有线程的情况则创建一个新的线程。
* 如果任务无法入队列(队列满了),那么我们将尝试新开启一个线程(从corepoolsize到扩充到maximum),如果失败了,那么可以确定原因,要么是线程池关闭了或者饱和了(达到maximum),所以我们执行拒绝策略。
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
int c = ctl.get();
//当前线程数量小于corePoolSize,则创建并启动线程。
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;// 成功,则返回
c = ctl.get();
}
//当前线程数大于等于核心线程数,进入阻塞队列,并且当前线程池的状态是运行态
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
// 入队列成功,检查线程池状态,如果状态部署RUNNING而且remove成功,则拒绝任务
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//无法入队,可能原因:当前线程数大于等于最大线程数,或者线程池处于shutdown或之后的状态,实施拒绝策略
else if (!addWorker(command, false))
reject(command);
}
addWorker()方法:
第二层for循环中判断条件的解析:
-
线程池的state越小越是运行状态,runnbale=-1,shutdown=0,stop=1,tidying=2,terminated=3
-
1、如果线程池state已经至少是shutdown状态了
-
2、并且以下3个条件任意一个是false
-
rs == SHUTDOWN (隐含:rs>=SHUTDOWN)
false情况: 线程池状态已经超过shutdown,可能是stop、tidying、terminated其中一个,即线程池已经终止 -
firstTask == null (隐含:rs == SHUTDOWN)
false情况: firstTask不为空,rs==SHUTDOWN 且 firstTask不为空,return false,场景是在线程池已经shutdown后,还要添加新的任务,拒绝 -
! workQueue.isEmpty() (隐含:rs == SHUTDOWN,firstTask==null)
false情况: workQueue为空,当firstTask为空时是为了创建一个没有任务的线程,再从workQueue中获取任务,如果workQueue已经为空,那么就没有添加新worker线程的必要了 -
return false,即无法addWorker()
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;
// 内层的循环,任务是将worker数量加1
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))//CAS
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
// worker加1后,接下来将woker添加到HashSet<Worker>中,并启动worker
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
final ReentrantLock mainLock = this.mainLock;//获取锁
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int c = ctl.get();
int rs = runStateOf(c);
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
private void addWorkerFailed(Worker w) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (w != null)
workers.remove(w);
decrementWorkerCount();
tryTerminate();
} finally {
mainLock.unlock();
}
}
final void reject(Runnable command) {
handler.rejectedExecution(command, this);
}
(2)shutdown():
shutdown()执行步骤:
1、上锁,mainLock是线程池的主锁,是可重入锁,当要操作workers set这个保持线程的HashSet时,需要先获取mainLock,还有当要处理largestPoolSize、completedTaskCount这类统计数据时需要先获取mainLock
2、判断调用者是否有权限shutdown线程池
3、使用CAS操作将线程池状态设置为shutdown,shutdown之后将不再接收新任务
4、中断所有空闲线程 interruptIdleWorkers()
5、onShutdown(),ScheduledThreadPoolExecutor中实现了这个方法,可以在shutdown()时做一些处理
6、解锁
7、尝试终止线程池 tryTerminate()
先前提交的任务将会被工作线程执行,新的线程将会被拒绝。
这个方法不会等待提交的任务执行完,我们可以用awaitTermination来等待任务执行完。
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//检查线程访问权限
checkShutdownAccess();
//CAS+更新线程池状态为SHUTDOWN
advanceRunState(SHUTDOWN);
//中断空闲工作线程
interruptIdleWorkers();
//线程池关闭hook
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate(); //尝试结束线程池
}
private void checkShutdownAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(shutdownPerm);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
//遍历工作线程集,检查任务线程访问权限
security.checkAccess(w.thread);
} finally {
mainLock.unlock();
}
}
}
private void advanceRunState(int targetState) {
for (;;) {
int c = ctl.get();
if (runStateAtLeast(c, targetState) ||
ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
break;
}
}
private void interruptIdleWorkers() {
//遍历工作线程集合,中断空闲工作线程
interruptIdleWorkers(false);
}
void onShutdown() {
}
final void tryTerminate() {
//自旋尝试关闭线程池
for (;;) {
int c = ctl.get();
//如果线程池正在运行,或正在关闭且任务队列不为空,则返回
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
if (workerCountOf(c) != 0) { // Eligible to terminate
//如果工作线程不为空,则中断空闲工作线程
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//线程池已关闭,任务队列为空,工作线程为0,更新线程池状态为TIDYING
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
//执行结束工作
terminated();
} finally {
//线程池已结束
ctl.set(ctlOf(TERMINATED, 0));
//唤醒等待线程池结束的线程
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
(3)shutdownNow():
* @throws SecurityException {@inheritDoc}尝试停止所有的活动执行任务、暂停等待任务的处理,并返回等待执行的任务列表。
*/
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//判断调用者是否有权限shutdown线程池
checkShutdownAccess();
//CAS+循环设置线程池状态为stop
advanceRunState(STOP);
//中断所有线程,包括正在运行任务的
interruptWorkers();
tasks = drainQueue();//将workQueue中的元素放入一个List并返回
} finally {
mainLock.unlock();
}
//尝试终止线程池
tryTerminate();
//返回workQueue中未执行的任务
return tasks;
}
shutdownNow() 和 shutdown()的大体步骤相似,不同之处是:
1、将线程池更新为stop状态
2、调用interruptWorkers()中断所有线程,包括正在运行的线程
3、将workQueue中待处理的任务移到一个List中,并在方法最后返回,说明shutdownNow()后不会再处理workQueue中的任务
线程池的实现
- 线程池的执行过程:
(1)判断当前线程池中的线程数是否小于核心线程数corePoolSize,小于则创建一个新线程执行任务;
(2)判断如果当前线程池中的线程数大于等于核心线程数corePoolSize,并且workQueue队列未满,则将该线程放入阻塞队列中,并且当前线程池的状态是运行态;
(3)判断如果线程池中的线程数量大于等于corePoolSize,且队列workQueue已满,但线程池中的线程数量小于maximumPoolSize,则会创建新的线程来处理被添加的任务;
(4)如果线程池中的线程数量等于了maximumPoolSize,就用RejectedExecutionHandler来执行拒绝策略;
* 线程池提交任务:
可以使用execute和submit两个方法向线程池提交任务。
(1)execute方法用于提交不需要返回值的任务,利用这种方式提交的任务无法得知是否正常执行;
(2)submit()方法用于提交需要返回值的任务。
线程池会返回一个Future类型的对象,通过这个Future对象可以判断任务是否执行成功,并且可以通过future的get()方法来获取返回值,get()方 法会阻塞当前线程直到任务完成,而使用get(long timeout,TimeUnit unit)方法则会阻塞当前线 程一段时间后立即返回,这时候有可能任务没有执行完。
submit()方法
submit()有3个参数不一的方法,这些方法都是在ExecutorService接口中声明的,在AbstractExecutorService中实现,而ThreadPoolExecutor继承AbstractExecutorService。
submit()方法接收实现Callable接口的的对象,同时还有一个重载的方法,重载方法接收实现Runnable方法的类。也就是说不管是实现了Runnable还是Callable的类都可以作为它的参数。submit()方法还有一个Future类型的返回值,Future用于获取线程的返回值,Future是一个有泛型的类,泛型的类型与Callable的泛型相同。
//ExecutorService声明:
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
// AbstractExecutorService实现:
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
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;
}
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
public interface Runnable {
void run();
}
public interface Callable<V> {
V call() throws Exception;
}
- 线程池的终止:
可以通过调用线程池的shutdown()或shutdownNow()方法来关闭线程池。
原理:
遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无响应中断的任务可能永远无法停止。shutdown()方法和shutdownNow()方法存在一定的区别,shutdownNow首先将线程池的状态设置为STOP,然后尝试停止所有正在执行或暂停任务的线程,并返回等待执行任务的列表,而shutdown只是将线程池的状态设置成SHUTDOWN状态,然后中断所有正在执行的任务。
只要调用了这两个关闭方法的一个,isShutdown()就会返回true。
当所有的任务都关闭后,才表示线程池关闭成功,这是调用isTerminated方法会返回true。
至于调用哪一种方法来关闭线程池,由提交到线程池的任务特性决定,通常调用shutdown方法来关闭线程池,如果任务不一定执行完,则可以调用shutdownNow方法。
shutdown方法只是发出了停止信号,等所有线程执行完毕会关闭线程池;
而shutdownNow则是立即停止所有任务。