一、問題描述
在程序設計中,可能存在這樣的情景:主線程中存在一個子線程,子線程需要在執行完畢后為后續代碼邏輯提供參數。但在代碼執行時,子進程還沒執行完畢,后續的代碼已經開始執行了,這時候就會出現參數為空的異常,或是直接報錯。
1 public class ThreadTest { 2 public static void main(String[] args) { 3 String str; 4 Thread thread = null; 5 thread = new Thread(new Runnable() { 6 @Override 7 public void run() { 8 while(true){ 9 System.out.println("Thread is running..."); 10 break; 11 } 12 } 13 }); 14 thread.start(); 15 16 System.out.println("Thread is finished..."); 17 } 18 }
執行結果:
因此,如何才能使得子進程執行完畢后才開始運行后續代碼呢?
二、解決方法
1. join
Thread類提供了一個join( )方法,其原理是不斷檢查子進程是否執行完畢,當子進程未執行完成時,調用該子進程的進程被阻塞,直到子進程執行完畢后,再繼續運行調用進程。
1 public class ThreadTest { 2 public static void main(String[] args) { 3 String str; 4 Thread thread = null; 5 thread = new Thread(new Runnable() { 6 @Override 7 public void run() { 8 while(true){ 9 System.out.println("Thread is running..."); 10 break; 11 } 12 } 13 }); 14 thread.start(); 15 try { 16 thread.join(); 17 } catch (InterruptedException e) { 18 e.printStackTrace(); 19 } 20 21 System.out.println("Thread is finished..."); 22 } 23 }
執行結果:
2. CountDownLatch
CountDownLatch允許一個或多個線程等待其他線程執行完畢后再運行。
- CountDownLatch的構造函數接收int類型的參數作為計數器,若要等待N個點再執行后續邏輯,就傳入N。
- 這里的N可以是N個線程,也可以是N個執行步驟。
- 當我們調用countDown( )方法時,N會減一。
- 調用await( ) 方法來阻塞當前線程,直到N減為0。
1 public class ThreadTest { 2 public static void main(String[] args) { 3 CountDownLatch count = new CountDownLatch(2); 4 String str; 5 Thread thread1, thread2 = null; 6 thread1 = new Thread(new Runnable() { 7 @Override 8 public void run() { 9 System.out.println("Thread1" + " is running..."); 10 count.countDown(); 11 System.out.println("Thread1 " + " is finished..."); 12 } 13 }); 14 thread2 = new Thread(new Runnable() { 15 @Override 16 public void run() { 17 System.out.println("Thread2" + " is running..."); 18 count.countDown(); 19 System.out.println("Thread2" + " is finished..."); 20 } 21 }); 22 thread1.start(); 23 thread2.start(); 24 try { 25 count.await(); 26 } catch (InterruptedException e) { 27 e.printStackTrace(); 28 } 29 System.out.println("All is finished."); 30 } 31 }
執行結果: