zoukankan      html  css  js  c++  java
  • 线程池如何保证所有子线程运行完再执行主线程

    转:https://blog.csdn.net/M983373615/article/details/97116131

    java主线程等待所有子线程执行完毕在执行,其实在我们的工作中经常的用到,比如说主线程要返回一个响应用户的值,但这个值得赋值过程是由过个子线程来完成的(模拟一个实际开发的情景),所以主线程必须等待子线程执行完毕,再响应用户;否则,响应用户的是一个无意义的值。

    那么如何确保所有的子线程执行完毕了。一般的有如下方法:

    使用 ExecutorService线程池,等待所有任务执行完毕再执行主线程,awaitTermination。
    我的解决办法如下:
    awaitTermination(long timeout,TimeUnit unit)
    请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行。
    解决方案:

    import java.util.concurrent.CountDownLatch;
    
    public class MyThread extends Thread {
        public MyThread(CountDownLatch threadSignal){
            System.out.println("线程子启动,需要5秒....");
            for (int i = 0; i < 5; i++) {
                System.out.print(i + 1+",");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("线程创建完毕.....");
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.print("i = " + i+",");
    
            }
            System.out.println();
        }
    }
    import java.util.concurrent.*;
    
    public class Demo {
        public static void main(String[] args) throws InterruptedException {
    
            // 初始化countDown
            CountDownLatch threadSignal = new CountDownLatch(5);
            // 使用线程池
            ExecutorService service = Executors.newScheduledThreadPool(5);
            MyThread myThread = new MyThread(threadSignal);
    
            for (int i=0;i<5;i++) {
                service.submit(myThread);
            }
    
            service.shutdown();
            // service.isTerminated()判断子线程是否全部完成;完成 :true;没完成 :falese
            System.out.println("调用awaitTermination之前:"+service.isTerminated());
            // 个人理解:如果service进行了shutdown操作,就查看子线程是否全部完成(也就是调用此方法),其中的参数相当于超时时间
            service.awaitTermination(1,TimeUnit.HOURS);
            System.out.println("调用awaitTermination之后:"+service.isTerminated());
            if (service.isTerminated()) {
                System.out.println("子线程执行完毕");
                System.out.println("主线程开始");
            }
    
        }
    }
    线程子启动,需要5秒....
    1,2,3,4,5,线程创建完毕.....
    睡两秒
    i = 0,i = 1,i = 2,i = 3,i = 4,i = 5,i = 6,i = 7,i = 8,i = 9,i = 10,i = 11,i = 12,i = 13,i = 14,i = 15,i = 16,i = 17,i = 18,i = 19,i = 20,i = 21,i = 22,i = 23,i = 24,i = 25,i = 0,i = 26,i = 1,i = 27,i = 28,i = 0,i = 2,i = 0,i = 1,i = 2,i = 29,i = 30,i = 31,i = 32,i = 3,i = 3,i = 0,i = 1,i = 2,i = 3,i = 4,i = 5,i = 6,i = 7,i = 8,i = 9,i = 10,i = 11,i = 12,i = 13,i = 14,i = 15,i = 16,i = 17,i = 18,i = 19,i = 20,i = 1,i = 4,i = 5,i = 6,i = 7,i = 8,i = 9,i = 10,i = 11,i = 12,i = 13,i = 14,i = 15,i = 16,i = 17,i = 18,i = 19,i = 20,i = 4,i = 33,i = 5,i = 6,i = 7,i = 8,i = 9,i = 10,i = 11,i = 12,i = 13,i = 14,i = 15,i = 16,i = 17,i = 18,i = 19,i = 20,i = 21,i = 22,i = 23,i = 24,i = 25,i = 26,i = 21,i = 22,i = 23,i = 2,i = 21,i = 22,i = 3,i = 4,i = 5,i = 6,i = 24,i = 27,i = 25,i = 26,i = 34,i = 35,i = 36,i = 37,i = 38,i = 39,i = 40,i = 41,i = 42,i = 43,i = 44,i = 45,i = 46,i = 47,i = 48,i = 49,i = 50,i = 51,i = 52,i = 53,i = 54,i = 55,i = 56,i = 57,i = 58,i = 59,i = 60,i = 61,i = 62,i = 27,i = 28,i = 7,i = 8,i = 9,i = 10,i = 11,i = 12,i = 13,i = 23,i = 24,i = 25,i = 26,i = 27,i = 28,i = 29,i = 30,i = 31,i = 32,i = 33,i = 14,i = 15,i = 29,i = 28,i = 63,i = 29,i = 30,i = 31,i = 30,i = 16,i = 34,i = 17,i = 31,i = 32,i = 33,i = 34,i = 35,i = 36,i = 37,i = 38,i = 39,i = 40,i = 41,i = 42,i = 43,i = 44,i = 45,i = 46,i = 47,i = 64,i = 48,i = 32,i = 18,i = 35,i = 19,i = 33,i = 65,i = 49,i = 66,i = 34,i = 20,i = 36,i = 37,i = 38,i = 39,i = 40,i = 41,i = 21,i = 35,i = 36,i = 37,i = 38,i = 39,i = 40,i = 41,i = 42,i = 43,i = 44,i = 67,i = 50,i = 68,i = 45,i = 22,i = 42,i = 23,i = 46,i = 69,i = 70,i = 51,i = 71,i = 47,i = 24,i = 43,i = 25,i = 48,i = 72,i = 52,i = 73,i = 74,i = 75,i = 53,i = 49,i = 26,i = 44,i = 27,i = 50,i = 54,i = 76,i = 55,i = 51,i = 28,i = 45,i = 29,i = 52,i = 56,i = 77,i = 78,i = 57,i = 58,i = 59,i = 60,i = 53,i = 30,i = 31,i = 46,i = 47,i = 48,i = 49,i = 50,i = 51,i = 52,i = 53,i = 54,i = 55,i = 56,i = 57,i = 58,i = 59,i = 60,i = 61,i = 62,i = 63,i = 64,i = 65,i = 66,i = 67,i = 68,i = 69,i = 70,i = 71,i = 72,i = 73,i = 74,i = 75,i = 76,i = 77,i = 78,i = 32,i = 54,i = 61,i = 79,i = 62,i = 55,i = 33,i = 34,i = 35,i = 56,i = 57,i = 58,i = 79,i = 59,i = 36,i = 63,i = 80,i = 64,i = 37,i = 60,i = 80,i = 61,i = 38,i = 65,i = 81,i = 66,i = 39,i = 62,i = 81,i = 63,i = 40,i = 67,i = 82,i = 68,i = 69,i = 41,i = 64,i = 65,i = 82,i = 66,i = 42,i = 70,i = 83,i = 71,i = 43,i = 67,i = 83,i = 68,i = 44,i = 72,i = 84,i = 73,i = 45,i = 69,i = 84,i = 70,i = 46,i = 74,i = 85,i = 75,i = 47,i = 71,i = 85,i = 72,i = 48,i = 76,i = 86,i = 77,i = 49,i = 78,i = 73,i = 86,i = 74,i = 79,i = 50,i = 51,i = 87,i = 52,i = 80,i = 75,i = 87,i = 76,i = 81,i = 53,i = 88,i = 54,i = 82,i = 77,i = 88,i = 78,i = 83,i = 55,i = 89,i = 56,i = 84,i = 79,i = 85,i = 89,i = 86,i = 80,i = 81,i = 57,i = 90,i = 58,i = 82,i = 87,i = 90,i = 88,i = 83,i = 84,i = 59,i = 91,i = 60,i = 85,i = 89,i = 91,i = 90,i = 86,i = 61,i = 92,i = 62,i = 87,i = 91,i = 92,i = 92,i = 88,i = 63,i = 93,i = 64,i = 89,i = 93,i = 93,i = 94,i = 90,i = 65,i = 66,i = 67,i = 94,i = 95,i = 96,i = 97,i = 98,i = 99,i = 68,i = 91,i = 95,i = 96,i = 97,i = 98,i = 99,
    i = 94,i = 95,i = 96,i = 97,i = 98,i = 99,
    i = 92,i = 93,i = 94,i = 69,i = 70,i = 71,i = 72,i = 73,i = 74,i = 75,i = 76,i = 77,i = 78,i = 79,i = 80,i = 81,i = 82,i = 83,i = 84,i = 85,i = 86,i = 87,i = 88,i = 89,
    i = 90,i = 91,i = 92,i = 93,i = 94,i = 95,i = 96,i = 97,i = 95,i = 96,i = 97,i = 98,i = 98,i = 99,
    i = 99,
    调用awaitTermination之前:true
    调用awaitTermination之后:true
    子线程执行完毕
    主线程开始

    其他:
    1、 让主线程等待,或着睡眠几分钟。用Thread.sleep()或者TimeUnit.SECONDS.sleep(5);

    如下:

    package andy.thread.traditional.test;
     
    import java.util.concurrent.TimeUnit;
     
    /**
     * @author Zhang,Tianyou
     * @version 2014年11月21日 下午11:15:27
     */
     
    public class ThreadSubMain1 {
     
      public static void main(String[] args) {
        // TODO Auto-generated method stub
     
        for (int i = 0; i < 10; i++) {
     
          new Thread(new Runnable() {
            public void run() {
     
              try {
                Thread.sleep(1000);
                // 模拟子线程任务
              } catch (InterruptedException e) {
              }
              System.out.println("子线程" + Thread.currentThread() + "执行完毕");
     
            }
          }).start();
          
        }
     
        try {
          // 等待全部子线程执行完毕
          TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
     
        System.out.println("主线执行。");
      }
     
    }
    子线程Thread[Thread-1,5,main]执行完毕
    子线程Thread[Thread-3,5,main]执行完毕
    子线程Thread[Thread-5,5,main]执行完毕
    子线程Thread[Thread-7,5,main]执行完毕
    子线程Thread[Thread-9,5,main]执行完毕
    子线程Thread[Thread-0,5,main]执行完毕
    子线程Thread[Thread-2,5,main]执行完毕
    子线程Thread[Thread-4,5,main]执行完毕
    子线程Thread[Thread-6,5,main]执行完毕
    子线程Thread[Thread-8,5,main]执行完毕
    主线执行。

    此方主线程只是睡了5秒,但是不能保证全部的子线程执行完成,所以这儿的5秒只是一个估值

    2 、使用Thread的join()等待所有的子线程执行完毕,主线程在执行

    实现 如下

    package andy.thread.traditional.test;
     
    import java.util.Vector;
     
    /**
     * @author Zhang,Tianyou
     * @version 2014年11月21日 下午11:15:27
     */
     
    public class ThreadSubMain2 {
     
      public static void main(String[] args) {
        // 使用线程安全的Vector 
        Vector<Thread> threads = new Vector<Thread>();
        for (int i = 0; i < 10; i++) {
     
          Thread iThread = new Thread(new Runnable() {
            public void run() {
     
              try {
                Thread.sleep(1000);
                // 模拟子线程任务
              } catch (InterruptedException e) {
              }
              System.out.println("子线程" + Thread.currentThread() + "执行完毕");
     
            }
          });
     
          threads.add(iThread);
          iThread.start();
        }
     
        for (Thread iThread : threads) {
          try {
            // 等待所有线程执行完毕
            iThread.join();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
     
        System.out.println("主线执行。");
      }
     
    }

    执行结果:

    子线程Thread[Thread-1,5,main]执行完毕
    子线程Thread[Thread-2,5,main]执行完毕
    子线程Thread[Thread-0,5,main]执行完毕
    子线程Thread[Thread-3,5,main]执行完毕
    子线程Thread[Thread-4,5,main]执行完毕
    子线程Thread[Thread-9,5,main]执行完毕
    子线程Thread[Thread-7,5,main]执行完毕
    子线程Thread[Thread-5,5,main]执行完毕
    子线程Thread[Thread-8,5,main]执行完毕
    子线程Thread[Thread-6,5,main]执行完毕
    主线执行。

    作者:guanbin —— 纵码万里千山

    出处:https://www.cnblogs.com/guanbin-529/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    angularjs: ng-select和ng-options
    angularjs之$timeout指令
    angular的uiRouter服务学习(5) --- $state.includes()方法
    深究AngularJS——如何获取input的焦点(自定义指令)
    深究AngularJS——自定义服务详解(factory、service、provider)
    AngularJS 事件指令/input相关指令/样式指令/DOM操作指令详解
    字符串对象的创建
    redis安装和配置
    Cent Linux启动tomcat慢的问题
    Linux环境nginx的配置
  • 原文地址:https://www.cnblogs.com/guanbin-529/p/14383651.html
Copyright © 2011-2022 走看看