这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭。
先来说说线程池的开启,这部分来看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;
}
可以看到,尽管设定了corePoolSize,也就是Worker线程的数量,但是线程池开启的时候,默认是没有创建这些Worker线程的,但是ThreadPoolExecutor提供了prestartAllCoreThreads方法来开启所有的预设的Worker线程,以及prestartCoreThread尝试开启一个预设的Worker线程。
这里重点说说handler,也就是RejectedExecutionHandler,拒绝任务的处理类,ThreadPoolExecutor提供四种策略:
1. CallerRunsPolicy
该策略会在ThreadPoolExecutor没有关闭的情况,依旧运行任务
2. AbortPolicy
该策略会抛出一个RejectedExecutionException
3. DiscardPolicy
该策略直接忽略该任务,不会有任何动作
4. DiscardOldestPolicy
该策略会在ThreadPoolExecutor没有关闭的情况,丢弃下一个将要执行的任务,把该任务加入到执行队列。
接下来说说关闭,ThreadPoolExecutor提供了shutdown和shutdownNow两种方式,从字面上就能看出区别,后者会尝试结束正在运行的任务。
先来看shutdown:
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // ScheduledThreadPoolExecutor的回调方法
} finally {
mainLock.unlock();
}
tryTerminate();
}
再看shutdownNow:
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;
}
两个方法的代码非常相似,区别在于:
1. shutdownNow的状态设置为STOP,shutdown的状态是SHUTDOWN
2. shutdownNow会中断所有线程,也就是所有任务,而shutdown仅仅中断空闲线程,不会影响正在执行的任务。
3. shutdownNow会导出未执行的任务。
两个方法都用到的checkShutdownAccess方法主要是检查方法调用者是否有权限中断Worker线程。
advanceRunState方法用于设定线程的状态,如果状态值大于等于该状态值则会返回。关于状态值参看 《java.util.concurrent 包源码阅读》11 线程池系列之ThreadPoolExecutor 第一部分。
关于interruptIdleWorkers和interruptWorkers,在上一篇文章曾经说过Worker线程具备锁的功能,因此可以通过tryLock来判断Worker线程是否处于空闲状态,这是两个方法的区别所在。
这一部分写的有些凌乱,各位见谅。