3.3 第三步:onShutdown() 一个空实现,暂不用关注这个没啥,就是个留空的方法 。

文章插图
3.4 总结shutdown() 方法干两件事:
- 把线程池状态置为 SHUTDOWN 状态
- 中断空闲线程
public static void test01() throws InterruptedException {// corePoolSize 是 2,maximumPoolSize 是 2ThreadPoolExecutor es = new ThreadPoolExecutor(2, 2,60L, TimeUnit.SECONDS,new LinkedBlockingQueue<>());es.prestartAllCoreThreads(); // 启动所有 workeres.execute(new Task()); // Task是一个访问某网站的 HTTP 请求,跑的慢,后面会贴出来完整代码,这里把他当做一个跑的慢的异步任务就行es.shutdown();es.execute(new Task()); // 在线程池 shutdown() 后 继续添加任务,这里预期是抛出异常}这个例子我们主要观察两个现象 。一个是线程池会有两个woker( prestartAllCoreThreads() 方法的调用使得已启动就有两个 worker),其中一个正在执行,一个处于空闲 。所以当调用shutdown() 方法,走进 interruptIdleWorkers() 的时候,只有那个空闲的线程会调用 t.interrupt() 。

文章插图
第二个是调用 shutdown() 方法后,再调用 execute() 时,会抛出异常,因为线程池的状态已经置为 SHUTDOWN,不再接受新的任务添加进来 。

文章插图
4 线程池的关闭 shutdownNow 方式
/** * Attempts to stop all actively executing tasks, halts the * processing of waiting tasks, and returns a list of the tasks * that were awaiting execution. These tasks are drained (removed) * from the task queue upon return from this method. * * <p>This method does not wait for actively executing tasks to * terminate.Use {@link #awaitTermination awaitTermination} to * do that. * * <p>There are no guarantees beyond best-effort attempts to stop * processing actively executing tasks.This implementation * cancels tasks via {@link Thread#interrupt}, so any task that * fails to respond to interrupts may never terminate. * * @throws SecurityException {@inheritDoc} */public List<Runnable> shutdownNow() {List<Runnable> tasks;final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {checkShutdownAccess();advanceRunState(STOP); // 1:把线程池设置为STOPinterruptWorkers(); // 2.中断工作线程tasks = drainQueue(); // 3.把线程池中的任务都 drain 出来} finally {mainLock.unlock();}tryTerminate();return tasks;}注释的意思是:尝试停止所有正在执行的任务,暂停正在等待的任务的处理,并返回等待执行的任务列表 。从该方法返回时 , 这些任务将从任务队列中清空(移除) 。
此方法不等待活动执行的任务终止 。如果需要,可使用 awaitTermination() 做到这一点 。
除了尽最大努力尝试停止处理主动执行的任务之外,没有其他保证 。
此实现通过 Thread.Interrupt() 取消任务,因此任何无法响应中断的任务都可能永远不会终止 。
4.1 第一步:advanceRunState() 把线程池设置为STOP和 shutdown() 方法不同的是 , shutdownNow() 方法会把线程池的状态设置为 STOP 。

文章插图
4.2 第二步:interruptWorkers() 中断工作线程interruptWorkers() 如下,可以看到,和 shutdown() 方法不同的是 , 所有的工作线程都调用了 interrupt() 方法
/** * Interrupts all threads, even if active. Ignores SecurityExceptions * (in which case some threads may remain uninterrupted). */private void interruptWorkers() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {for (Worker w : workers)w.interruptIfStarted();} finally {mainLock.unlock();}}4.3 第三步:drainQueue() 把线程池中的任务都 drain 出来drainQueue() 方法如下,把阻塞队列里面等待的任务都拿出来,并返回 。关闭线程池的时候,可以基于这个特性,把返回的任务都打印出来,做个记录 。/** * Drains the task queue into a new list, normally using * drainTo. But if the queue is a DelayQueue or any other kind of * queue for which poll or drainTo may fail to remove some * elements, it deletes them one by one. */private List<Runnable> drainQueue() {BlockingQueue<Runnable> q = workQueue;ArrayList<Runnable> taskList = new ArrayList<Runnable>();q.drainTo(taskList);if (!q.isEmpty()) {for (Runnable r : q.toArray(new Runnable[0])) {if (q.remove(r))taskList.add(r);}}return taskList;}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Docker容器如何打包应用程序的代码和依赖项?
- SpringBoot中如何优雅地个性化定制Jackson
- 基于云的生成式AI,自己构建,还是购买?
- 搜索引擎优化中H1标签重要吗?介绍h1标签的主要功能
- 如何选择合适的虚拟防关联浏览器
- 快速建站如何保证网站的质量和效果?
- 揭秘“双赢式”网络推广:搜索引擎优化与竞价排名的完美结合
- 掌握了解网站优化特点,才能网站的权重稳步增加
- 为什么新做的网站搜索引擎不收录?
- 搜索引擎的工作原理,稳定网站自然排名
