天天看點

JAVA多線程之CountDownLatch

前序:

上周測試給開發的同僚所開發的子產品提出了一個bug,并且還是偶現。

經過仔細檢視代碼,發現是在業務中啟用了多線程,2個線程同時跑,但是新啟動的2個線程必須保證一個完成之後另一個再繼續運作,才能消除bug。

什麼時候用?

多線程是在很多地方都會用到的,但是我們如果想要實作在某個特定的線程運作完之後,再啟動另外一個線程呢,這個時候CountDownLatch就可以派上用場了

怎麼用?

先看看普通的多線程代碼:

1 package code;
 2 
 3 public class MyThread extends Thread { 
 4     public static void main(String[] args) {      
 5         MyThread th = new MyThread();   
 6         Thread t1 = new Thread(th, "Mythread");        
 7         t1.start();  
 8         System.out.println(Thread.currentThread().getName());  
 9         }        
10         public void run() 
11             {     
12                 Mythread1 th2 = new Mythread1();   
13                 Thread t2 = new Thread(th2, "Mythread1");        
14                 t2.start();  
15                 System.out.println(this.currentThread().getName());  
16             }  
17         class Mythread1 extends Thread
18         {
19             public void run() {    
20                 try {
21                     Thread.sleep(1000);
22                 } catch (InterruptedException e) {
23                     // TODO Auto-generated catch block
24                     e.printStackTrace();
25                 }
26                 System.out.println(this.currentThread().getName()); 
27                 }  
28             
29         }
30     }      

代碼如上,先用MyThread繼承了Thread類,然後在MyThread類内部又寫了一個MyThread1類,同樣也是繼承了Thread類,并且在run方法裡面讓它睡1秒,這樣運作代碼,就會列印出:

JAVA多線程之CountDownLatch

從上面的輸出順序可以看出,先是啟動了main線程,然後再啟動了MyThread線程,在MyThread線程中,又啟動了MyThread1線程。但是由于讓MyThread1線程睡了1秒,模拟處理後續業務,這樣他就比MyThread運作完畢的時間晚一些。

現在,在代碼中加上CountDownLatch ,要讓MyThread1先運作完畢,再讓MyThread繼續運作。

1 package code;
 2 
 3 import java.util.concurrent.CountDownLatch;
 4 
 5 public class MyThread extends Thread { 
 6     CountDownLatch countDownLatch = new CountDownLatch(1);
 7     public static void main(String[] args) {      
 8         MyThread th = new MyThread();   
 9         Thread t1 = new Thread(th, "Mythread");        
10         t1.start();  
11         System.out.println(Thread.currentThread().getName());  
12         }        
13         public void run() 
14             {     
15                 Mythread1 th2 = new Mythread1();   
16                 Thread t2 = new Thread(th2, "Mythread1");        
17                 t2.start();  
18                 try {
19                     countDownLatch.await();
20                 } catch (InterruptedException e) {
21                     e.printStackTrace();
22                 }
23                 System.out.println(this.currentThread().getName());  
24             }  
25         class Mythread1 extends Thread
26         {
27             public void run() {    
28                 try {
29                     Thread.sleep(1000);
30                 } catch (InterruptedException e) {
31                     e.printStackTrace();
32                 }
33                 System.out.println(this.currentThread().getName()); 
34                 countDownLatch.countDown();
35                 }  
36             
37         }
38     }      

代碼寫法如上所示,大緻分三步

1,我們先new一個CountDownLatch對象入參設定為1(我個人了解的這個就像是new一個數組一樣,什麼時候數組清空了,那就可以讓被中斷的線程繼續運作了)

2,在MyThread類中調用countDownLatch.await();讓目前線程停止運作。

3,在Mythread1類中調用countDownLatch.countDown()方法。當Mythread1全部執行完畢,再最後調用該方法,作用就是把我說的“數組”清空。

看看輸出的列印結果

JAVA多線程之CountDownLatch

結果如上圖,是符合預期的結果的。

最後再說下CountDownLatch countDownLatch = new CountDownLatch(1)的入參,這塊設定的是1,那就需要調用一次countDownLatch.countDown()減去1。

如果是其他數字,那就要調用相應的次數,否則調用countDownLatch.await()的線程都不會被繼續執行。

give me the ball!