java关闭线程池中的线程,如何优雅关闭线程池

  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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: