• Java并发编程系列32:线程池shutdown()和exs.isTerminated()结合使用


    出现问题:线程池就一直存在,程序停滞

    线程池使用时,如果没有使用shutdown()去停止时,线程池就一直存在,程序停滞。

    1. package runnable;
    2. import java.util.concurrent.ExecutorService;
    3. import java.util.concurrent.Executors;
    4. import java.util.concurrent.ThreadPoolExecutor;
    5. /**
    6. * ClassName ThreadPoolDemo5
    7. * description isTerminated方法使用
    8. *
    9. * @author : HMF
    10. * date: 2022/7/20 11:08
    11. **/
    12. class Runnable5 implements Runnable{
    13. @Override
    14. public void run() {
    15. for(int i=0;i<10000;i++){
    16. if(i==999){
    17. System.out.println(Thread.currentThread().getName()+",线程在执行:"+i);
    18. }
    19. }
    20. }
    21. }
    22. public class ThreadPoolDemo5 {
    23. public static void main(String[] args) {
    24. //创建Runnable 对象
    25. Runnable5 rt = new Runnable5();
    26. int ThreadNum=10;
    27. ExecutorService exs = Executors.newFixedThreadPool(ThreadNum);
    28. for(int i=0;i
    29. exs.execute(rt);
    30. }
    31. }
    32. }

    执行结果:

     解决方法:shutdown()停止,isTerminated()判断是否结束

    多线程中使用线程池,例如:newFixedThreadPool 等4种线程池或自定义线程池时,需要使用停止线程,并需要判断是否线程池是否停止。

    具体方法:

    • shutdown(),它可以安全地关闭一个线程池

    调用 shutdown() 方法之后线程池并不是立刻就被关闭,因为这时线程池中可能还有很多任务正在被执行,或是任务队列中有大量正在等待被执行的任务,调用 shutdown() 方法后线程池会在执行完正在执行的任务和队列中等待的任务后才彻底关闭。

    调用 shutdown() 方法后如果还有新的任务被提交,线程池则会根据拒绝策略直接拒绝后续新提交的任务。

    1. exs.shutdown();
    2. Runnable5 rt2 = new Runnable5();
    3. exs.execute(rt2);

    •  isTerminated() 判断方式,在执行 shutdown() ,关闭线程池后,判断是否所有任务已经完成。

      这个方法可以检测线程池是否真正“终结”了,这不仅代表线程池已关闭,同时代表线程池中的所有任务都已经都执行完毕了。

      直到所有任务都执行完毕了,调用 isTerminated() 方法才会返回 true,这表示线程池已关闭并且线程池内部是空的,所有剩余的任务都执行完毕了。

    1. package runnable;
    2. import java.util.concurrent.ExecutorService;
    3. import java.util.concurrent.Executors;
    4. /**
    5. * ClassName ThreadPoolDemo5
    6. * description isTerminated方法使用
    7. *
    8. * @author : HMF
    9. * date: 2022/7/20 11:08
    10. **/
    11. class Runnable5 implements Runnable{
    12. @Override
    13. public void run() {
    14. for(int i=0;i<10000;i++){
    15. if(i==999){
    16. System.out.println(Thread.currentThread().getName()+",线程在执行:"+i);
    17. }
    18. }
    19. }
    20. }
    21. public class ThreadPoolDemo5 {
    22. public static void main(String[] args) {
    23. //创建Runnable 对象
    24. Runnable5 rt = new Runnable5();
    25. int ThreadNum=10;
    26. ExecutorService exs = Executors.newFixedThreadPool(ThreadNum);
    27. for(int i=0;i
    28. exs.execute(rt);
    29. }
    30. exs.shutdown();
    31. isTerminated(exs,1);
    32. }
    33. public static void isTerminated(ExecutorService exs,int time){
    34. if(!exs.isTerminated()){
    35. try {
    36. System.out.println("线程池结束状态:"+exs.isTerminated());
    37. Thread.sleep(time);
    38. isTerminated(exs,time);
    39. }
    40. catch (Exception e){
    41. System.out.println(e);
    42. }
    43. }else {
    44. System.out.println("线程池结束状态::"+exs.isTerminated());
    45. }
    46. }
    47. }

    执行结果:

    第一次判断线程池如果未结束,休眠1秒钟再去判断(循环判断),知道线程池结束。

  • 相关阅读:
    Codeforces Round #835 (Div. 4)
    C#反射实现插件式开发
    什么人适合学NPDP产品经理认证?
    C语言:练习题三
    【Linux Shell脚本攻略】第1章 小试牛刀
    BSP3 电力监控仪(功率监控仪)端子定义和接线
    路由策略和路由控制
    微信小程序---npm 支持
    开发者专访|我从「人间地狱」的算法岗内卷中,倔强地踏出了一条路 前路漫漫,星芒万里
    Centos (含Rocky-Linux) VSFTPD 简单设置
  • 原文地址:https://blog.csdn.net/fen_fen/article/details/125888813