天天看點

java 多線程程式設計之CountDownLatch

CountDownLatch類位于java.util.concurrent包下,利用它可以實作類似計數器的功能。CountDownLatch的一個非常典型的應用場景是:有一個任務想要往下執行,但必須要等到其他的任務執行完畢後才可以繼續往下執行。假如我們這個想要繼續往下執行的任務調用一個CountDownLatch對象的await()方法,其他的任務執行完自己的任務後調用同一個CountDownLatch對象上的countDown()方法,這個調用await()方法的任務将一直阻塞等待,直到這個CountDownLatch對象的計數值減到0為止。

CountDownLatch類隻提供了一個構造器:

public CountDownLatch(int count) {  };  //參數count為計數值
           

下面這3個方法是CountDownLatch類中最重要的方法:

public void await() throws InterruptedException { };   //調用await()方法的線程會被挂起,它會等待直到count值為0才繼續執行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  //和await()類似,隻不過等待一定的時間後count值還沒變為0的話就會繼續執行
public void countDown() { };  //将count值減1
           

CountDownLatch的用法示例:

//一個CountDouwnLatch執行個體是不能重複使用的,也就是說它是一次性的,鎖一經被打開就不能再關閉使用了,如果想重複使用,請考慮使用CyclicBarrier。
public class CountDownLatchTest {
 // 模拟了100米賽跑,10名選手已經準備就緒,隻等裁判一聲令下。當所有人都到達終點時,比賽結束。
 public static void main(String[] args) throws InterruptedException {
     // 開始的倒數鎖 
     final CountDownLatch begin = new CountDownLatch(1);  
     // 結束的倒數鎖 
     final CountDownLatch end = new CountDownLatch(10);  
     // 十名選手 
     final ExecutorService exec = Executors.newFixedThreadPool(10);  
     for (int index = 0; index < 10; index++) {
         final int NO = index + 1;  
         Runnable run = new Runnable() {
             public void run() {  
                 try {  
                     // 如果目前計數為零,則此方法立即傳回。
                     // 等待
                	 System.out.println("await before====="+NO);
                     begin.await();  
                     Thread.sleep((long) (Math.random() * 10000));  
                     System.out.println("No." + NO + " arrived");  
                 } catch (InterruptedException e) {  
                	 
                 } finally {  
                     // 每個選手到達終點時,end就減一
                     end.countDown();
                 }  
             }  
         };  
         exec.submit(run);
     }  
     System.out.println("Game Start");  
     // begin減一,開始遊戲
     begin.countDown();  
     // 等待end變為0,即所有選手到達終點
     end.await();  
     System.out.println("Game Over");  
     exec.shutdown();  
 }
}