線程池如何保證所有子線程運行完再執行主線程


轉: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]執行完畢
主線執行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM