java关闭线程池中的线程,如何优雅关闭线程池
00-1010前言1。关闭线程1.1 volatile关键字1.2 intrrrupt()方法2。关闭线程池2.1 shutdownNow()方法2.2 shutdown()方法
00-1010这个问题是高频面试问题。
印象中是由stop方法执行或者由kill在终端中杀死。
但是,这些方法简单粗暴,不安全,不普及。
不间断方法
之所以不安全,不推广,是因为:
stop方法不管线程逻辑是否完整都会终止当前运行的线程,这样会破坏它的原子逻辑(多线程和锁解决了资源共享,但是stop会丢弃它所有的锁,造成混乱)。
目录
00-1010使用自定义标志位来确定线程的执行。
具体思路如下:设置一个父线程的状态变量来影响其子线程。
class test extends thread {//标识线程是否结束;公共静态布尔thread _ stop=truepublic void stop thread(){ thread _ stop=false;} public static void main(String[]args){ test t=new test();t . start();System.out.println(“父线程开始”);Try {//让线程先运行thread . sleep(2);} catch(interrupted exception e){ e . printstacktrace();}//结束线程//直接将其状态变量改为false//thread _ stop=false;//调用方法改为false(和直接修改状态变量的原因一样)t . stop thread();System.out.println(“父线程结束”);} @ Override public void run(){ while(Thread _ stop){ system . out . println(子线程开始);} System.out.println(子线程结束);}}但是网上说没有volatile停不下来,其实可以停。
仅仅
添加volatile有几个优点:
Volatile可以确保状态变量是系统内存值而不是缓存值(避免值不一致)。volatile关键字可以让变量对其他线程“可见”,即当主线程修改变量并刷新到主存时,会让其他线程读取主存中的变量。当然,volatile不能保证线程的安全性。具体来说,它被添加到状态变量中,如下所示:
//标识线程是否结束公共静态可变布尔thread _ stop=true之后,具体而完整的输出是:
完整的输出是:
父线程开始子线程开始子线程开始.子线程开始子线程开始父线程结束子线程结束
00-1010不能终止正在执行的线程,它只是修改中断标志。
这种方法分为两种情况:
线程被阻塞:立即退出块并抛出InterruptedException。通过捕捉这个异常,让线程退出。
线程处于非阻塞状态:它在运行时不受影响,只有线程的中断被标记为真。在适当的位置调用isInterrupted方法,查看它是否被中断并退出。
公共类test扩展线程{ public static void main(String[]args){ test t=new test();t . start();System.out.println(Fathe
r Thread Start"); try { //先让线程跑起来 Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } //结束线程 t.interrupt(); System.out.println("Father Thread end"); } @Override public void run() { //分配线程的中断状态,并且此状态可以由interrupted()方法生成 while (!Thread.interrupted()) { System.out.println("Child Thread Start"); } System.out.println("Child Thread end"); }}执行结果截图:
具体完整的输出为:
Father Thread startChild Thread StartChild Thread Start。。。。。。Child Thread StartChild Thread StartFather Thread endChild Thread end
2.关闭线程池
优雅的关闭线程池:(比如ThreadPoolExecutor类)
可以通过shutdown方法逐步关闭池中的线程(温和安全)
shutdown():拒收新任务,不会立即终止线程池。而是要等所有任务缓存队列中的任务都执行完后才终止。
shutdownNow():拒收新任务,立即终止线程池。并尝试打断正在执行的任务。
并且清空任务缓存队列,返回尚未执行的任务
以下是对两个线程池关闭的方法源代码进行分析
而且关闭的途中,这两个方法也不是瞬间立马关闭,等待关闭的同时,还还调用awaitTermination方法来阻塞等待
2.1 shutdownNow()方法
查看java的源代码
在try内部结构中
1.检查其状态
2.原子性的修改线程池的状态为stop
3.遍历工作队列线程,调用interrupt方法
4.将队列中还未执行的放到任务队列
源码内部:其逻辑就是修改线程池状态为stop,工作队列中调用interrupt方法
在调用shutdownNow方法:
正在执行的线程会(getTask返回null)导致线程退出。队列中读取的任务会阻塞,抛出异常之后。工作队列就会调用interrupt方法
2.2 shutdown()方法
同样也是看java的源代码
同样也是4步状态
1.检查其状态
2.修改线程池状态为SHUTDOWN
3.调用interruptIdleWorkers方法中断空闲线程(只有加锁成功的线程才会被调用interrupt方法)
而正在执行的线程是加锁失败,不会被中断
主要通过这个函数去区分判断
以上就是详解Java如何关闭线程以及线程池的详细内容,更多关于Java关闭线程 线程池的资料请关注盛行IT其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。