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