正确关闭线程池:shutdown 和 shutdownNow 的区别
点击关注公众号,实用技术文章及时了解
来源:blog.csdn.net/xiewenfeng520/
article/details/107013342
前言
本章分为两个议题
如何正确关闭线程池
shutdown 和 shutdownNow 的区别
项目环境
jdk 1.8
github 地址:https://github.com/huajiexiewenfeng/java-concurrent
本章模块:threadpool
1.线程池示例
public class ShutDownThreadPoolDemo {private ExecutorService service = Executors.newFixedThreadPool(10);public static void main(String[] args) {new ShutDownThreadPoolDemo().executeTask();}public void executeTask() {for (int i = 0; i < 100; i++) {service.submit(() -> {System.out.println(Thread.currentThread().getName() + "->执行");});}}}
执行结果
pool-1-thread-2->执行
pool-1-thread-3->执行
pool-1-thread-1->执行
pool-1-thread-4->执行
pool-1-thread-5->执行
pool-1-thread-6->执行
...
执行完成之后,主线程会一直阻塞,那么如何关闭线程池呢?本章介绍 5 种在 ThreadPoolExecutor 中涉及关闭线程池的方法,如下所示
void shutdown
boolean isShutdown
boolean isTerminated
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
List<Runnable> shutdownNow
2.shutdown
第一种方法叫作 shutdown(),它可以安全地关闭一个线程池,调用 shutdown() 方法之后线程池并不是立刻就被关闭,因为这时线程池中可能还有很多任务正在被执行,或是任务队列中有大量正在等待被执行的任务,调用 shutdown() 方法后线程池会在执行完正在执行的任务和队列中等待的任务后才彻底关闭。
调用 shutdown() 方法后如果还有新的任务被提交,线程池则会根据拒绝策略直接拒绝后续新提交的任务。学习资料:Java进阶视频资源
这段源码位置(jdk 1.8 版本)
java.util.concurrent.ThreadPoolExecutor#execute
public void execute(Runnable command) {if (command == null)throw new NullPointerException();int c = ctl.get();// 线程池中的线程比核心线程数少 if (workerCountOf(c) < corePoolSize) {// 新建一个核心线程执行任务if (addWorker(command, true))return;c = ctl.get();}// 核心线程已满,但是任务队列未满,添加到队列中if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();// 任务成功添加到队列以后,再次检查是否需要添加新的线程,因为已存在的线程可能被销毁了if (! isRunning(recheck) && remove(command))// 如果线程池处于非运行状态,并且把当前的任务从任务队列中移除成功,则拒绝该任务reject(command);else if (workerCountOf(recheck) == 0)// 如果之前的线程已经被销毁完,新建一个非核心线程addWorker(null, false);}// 核心线程池已满,队列已满,尝试创建一个非核心新的线程else if (!addWorker(command, false))// 如果创建新线程失败,说明线程池关闭或者线程池满了,拒绝任务reject(command);}
1373 行
if (! isRunning(recheck) && remove(command))
如果线程池被关闭,将当前的任务从任务队列中移除成功,并拒绝该任务1378 行
else if (!addWorker(command, false))
如果创建新线程失败,说明线程池关闭或者线程池满了,拒绝任务。
3.isShutdown
第二个方法叫作 isShutdown(),它可以返回 true 或者 false 来判断线程池是否已经开始了关闭工作,也就是是否执行了 shutdown 或者 shutdownNow 方法。
这里需要注意,如果调用 isShutdown() 方法的返回的结果为 true 并不代表线程池此时已经彻底关闭了,这仅仅代表线程池开始了关闭的流程,也就是说,此时可能线程池中依然有线程在执行任务,队列里也可能有等待被执行的任务。
4.isTerminated
第三种方法叫作 isTerminated(),这个方法可以检测线程池是否真正“终结”了,这不仅代表线程池已关闭,同时代表线程池中的所有任务都已经都执行完毕了。
比如我们上面提到的情况,如果此时已经调用了 shutdown 方法,但是还有任务没有执行完,那么此时调用 isShutdown 方法返回的是 true,而 isTerminated 方法则会返回 false。
直到所有任务都执行完毕了,调用 isTerminated() 方法才会返回 true,这表示线程池已关闭并且线程池内部是空的,所有剩余的任务都执行完毕了。
学习资料:Java进阶视频资源
5.awaitTermination
第四个方法叫作 awaitTermination(),它本身并不是用来关闭线程池的,而是主要用来判断线程池状态的。
比如我们给 awaitTermination 方法传入的参数是 10 秒,那么它就会陷入 10 秒钟的等待,直到发生以下三种情况之一:
等待期间(包括进入等待状态之前)线程池已关闭并且所有已提交的任务(包括正在执行的和队列中等待的)都执行完毕,相当于线程池已经“终结”了,方法便会返回 true
等待超时时间到后,第一种线程池“终结”的情况始终未发生,方法返回 false
等待期间线程被中断,方法会抛出 InterruptedException 异常
调用 awaitTermination 方法后当前线程会尝试等待一段指定的时间,如果在等待时间内,线程池已关闭并且内部的任务都执行完毕了,也就是说线程池真正“终结”了,那么方法就返回 true,否则超时返回 fasle。
6.shutdownNow
最后一个方法是 shutdownNow(),它和 shutdown() 的区别就是多了一个 Now,表示立刻关闭的意思,不推荐使用这一种方式关闭线程池。
在执行 shutdownNow 方法之后,首先会给所有线程池中的线程发送 interrupt 中断信号,尝试中断这些任务的执行,然后会将任务队列中正在等待的所有任务转移到一个 List 中并返回,我们可以根据返回的任务 List 来进行一些补救的操作,例如记录在案并在后期重试。
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;}
interruptWorkers
让每一个已经启动的线程都中断,这样线程就可以在执行任务期间检测到中断信号并进行相应的处理,提前结束任务
7.shutdown 和 shutdownNow 的区别?
shutdown 会等待线程池中的任务执行完成之后关闭线程池,而 shutdownNow 会给所有线程发送中断信号,中断任务执行,然后关闭线程池
shutdown 没有返回值,而 shutdownNow 会返回关闭前任务队列中未执行的任务集合(List)
8.参考
《Java 并发编程 78 讲》- 徐隆曦
推荐:
主流Java进阶技术(学习资料分享)
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!
正确关闭线程池:shutdown 和 shutdownNow 的区别相关推荐
- 关闭线程池 shutdown 和 shutdownNow 的区别
欢迎关注方志朋的博客,回复"666"获面试宝典 来源:https://blog.csdn.net/xiewenfeng520/article/details/107013342 前 ...
- 关闭线程池 shutdown 和 shutdownNow 的区别?
前言 本章分为两个议题 如何正确关闭线程池 shutdown 和 shutdownNow 的区别 1.线程池示例 public class ShutDownThreadPoolDemo {privat ...
- Java多线程 关闭线程池 shutdown() 、shutdownNow()、awaitTermination()
目录 一.说明 二.理解 三.实现 1.shutdown() 2.shutdownNow() 3.awaitTermination() 一.说明 ThreadPoolExecutor 继承 Execu ...
- Java多线程学习九:如何正确关闭线程池?shutdown 和 shutdownNow 的区别
如何正确关闭线程池?以及 shutdown() 与 shutdownNow() 方法的区别?首先,我们创建一个线程数固定为 10 的线程池,并且往线程池中提交 100 个任务,如代码所示. 复制代码 ...
- 线程池shutdown和shutdownNow原理和区别
说明:以ThreadPoolExecutor线程池为例说明整个流程(不同的线程池实现上略有差别). 一.shutdown流程 1.流程简介 修改线程池状态为SHUTDOWN 不再接收新提交的任务 中断 ...
- mysql 关闭线程池_线程池安全的关闭方式
对于一些定时任务或者网络请求服务将会使用线程池,当应用停机时需要正确安全的关闭线程池,如果处理不当,可能造成数据丢失,业务请求结果不正确等问题. 关闭线程池我们可以选择什么都不做,JVM 关闭时自然的 ...
- java线程池shutdown_关闭线程池的正确姿势,shutdown(), shutdownNow()和awaitTermination() 该怎么用?...
关闭线程池的正确姿势,shutdown(), shutdownNow()和awaitTermination() 该怎么用? ExecutorService 接口提供了三个方法用于手动关闭线程池,分别是 ...
- ThreadPoolExecutor线程池,shutdown和shutdownNow关闭线程池方式对比,以及确保线程池能够彻底关闭的一种方式
1. ThreadPoolExecutor线程池 1.1 创建线程池,构造方法的几个参数说明及创建如下. 1.2 shutdown方式关闭线程池 a. 空闲且能interrupt表示该线程处于阻塞等待 ...
- 如何关闭线程池?会创建不会关闭?调用关闭方法时线程池里的线程如何反应?
前言 相信大家在面试的时候经常会遇到「线程池」相关的问题,比如: 什么是线程池?线程池的优点? 有哪几种创建线程池的方式? 四种创建线程池的使用场景? 线程池的底层原理? 线程池相关的参数,比如Cor ...
最新文章
- Playboy封面女郎、互联网第一夫人,程序员们的“钢铁审美”
- SpringBoot配置文件放在jar外部
- Spring与Hibernate整合中,使用OpenSessionInViewFilter后出现sessionFactory未注入问题
- Android隐藏输入法键盘(hideSoftInputFromInputMethod没有效果)(转)
- 他人收藏的精彩视频(一)
- Win7下的使用QTP进行猴子测试的性能日志实现方法
- 北上广深杭程序员买房姿势图鉴
- 《Linux 性能及调优指南》1.4 硬盘I/O子系统
- Angular学习笔记(五) - 自定义表单控件
- 力扣-605 种花问题
- 以太坊虚拟机 EVM(3)交易流(FISCO BCOS为例)
- 吉他扒谱该怎么做?分享一款超好用的扒谱工具!
- 尾注参考文献之后添加附录致谢解决办法
- Arm电脑出现【GLFWError】WGL: The driver does not appear to support OpenGL问题解决
- nodejs使用node-ffi-napi 访问dll文件
- List、Map 与json转换的工具类
- 艾司博讯:拼多多全店推广是什么意思?
- 孔浩java爱酷网_孔浩老师JAVA WebService教程
- 根据TXT文件中的文件名复制文件
- 3-4 harbor 2.6.2 的安装使用及高可用方案