已同步更新至:http://dxjia.cn/2015/08/countdownlatch-use/
有時候會有這樣的需求,多個線程同時工作,然后其中幾個可以隨意並發執行,但有一個線程需要等其他線程工作結束后,才能開始。舉個例子,開啟多個線程分塊下載一個大文件,每個線程只下載固定的一截,最后由另外一個線程來拼接所有的分段,那么這時候我們可以考慮使用CountDownLatch來控制並發。
CountDownLatch是JAVA提供在java.util.concurrent包下的一個輔助類,可以把它看成是一個計數器,其內部維護着一個count計數,只不過對這個計數器的操作都是原子操作,同時只能有一個線程去操作這個計數器,CountDownLatch通過構造函數傳入一個初始計數值,調用者可以通過調用CounDownLatch對象的cutDown()方法,來使計數減1;如果調用對象上的await()方法,那么調用者就會一直阻塞在這里,直到別人通過cutDown方法,將計數減到0,才可以繼續執行。
示例
1 import java.util.concurrent.CountDownLatch; 2 3 public class Sample { 4 /** 5 * 計數器,用來控制線程 6 * 傳入參數2,表示計數器計數為2 7 */ 8 private final static CountDownLatch mCountDownLatch = new CountDownLatch(2); 9 10 /** 11 * 示例工作線程類 12 */ 13 private static class WorkingThread extends Thread { 14 private final String mThreadName; 15 private final int mSleepTime; 16 public WorkingThread(String name, int sleepTime) { 17 mThreadName = name; 18 mSleepTime = sleepTime; 19 } 20 21 @Override 22 public void run() { 23 System.out.println("[" + mThreadName + "] started!"); 24 try { 25 Thread.sleep(mSleepTime); 26 } catch (InterruptedException e) { 27 e.printStackTrace(); 28 } 29 mCountDownLatch.countDown(); 30 System.out.println("[" + mThreadName + "] end!"); 31 } 32 } 33 34 /** 35 * 示例線程類 36 */ 37 private static class SampleThread extends Thread { 38 39 @Override 40 public void run() { 41 System.out.println("[SampleThread] started!"); 42 try { 43 // 會阻塞在這里等待 mCountDownLatch 里的count變為0; 44 // 也就是等待另外的WorkingThread調用countDown() 45 mCountDownLatch.await(); 46 } catch (InterruptedException e) { 47 48 } 49 System.out.println("[SampleThread] end!"); 50 } 51 } 52 53 public static void main(String[] args) throws Exception { 54 // 最先run SampleThread 55 new SampleThread().start(); 56 // 運行兩個工作線程 57 // 工作線程1運行5秒 58 new WorkingThread("WorkingThread1", 5000).start(); 59 // 工作線程2運行2秒 60 new WorkingThread("WorkingThread2", 2000).start(); 61 } 62 }
運行結果:
[SampleThread] started!
[WorkingThread1] started!
[WorkingThread2] started!
[WorkingThread2] end!
[WorkingThread1] end!
[SampleThread] end!
達到了目的。當然還有其他方式可以做到這樣的效果,本文僅僅是介紹了一種使用CountDownLatch的方式。