Latch可以於當一個線程需要等候其它線程完成後再執行的情形java.util.concurrent包中CountDownLatch類實現了Latch功能,CountDownLatch(n)的構造函數中設置參與的線程數,await()用於等待其它線程,countDown()方法減少Latch的計數,如果計數達到零,則釋放所有等待的線程.
用例:
- 要對某個方法做併發測試時(CountDownLatch參與者設爲1,其它線程run()方法裏調用await(),所有線程初始化完成後,主線程調用countDown()方法,讓所有線程同時執行),
- 要從多個數據表中取得數據後,對這些數據進行加工,可以用多個線程去數據庫查詢數據,完成後設置countDown(),主線程用await()方法等候所有線程查詢完成後,分類彙總。
用CountDownLatch實現一個旅遊的例子,一開始導遊在一個指定地方等所有遊客到來,所有遊客到齊後,行程開始。
Tourist類繼承Thread類,代表一個遊客,讓Thread.sleep()生成一個隨機時間,代表遊客路上花費的時間,當到達後調用countDown方法,減少一個CountDownLatch的計數。
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Tourist extends Thread {
private final CountDownLatch latch;
private final String name;
public Tourist(CountDownLatch latch, String name) {
this.latch = latch;
this.name = name;
}
@Override
public void run() {
try {
long duration = (long) (Math.random() * 10);
TimeUnit.SECONDS.sleep(duration);
System.out.printf("%s has arrived\n", name);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();
}
}
}
Guide類代表一個導遊,當導遊到達集合地點,調 await()方法等Tourist到來,當所有人到達以後,則行程開始。
public class Guide extends Thread { private CountDownLatch latch; public Guide(CountDownLatch latch) { this.latch=latch; } @Override public void run() { try { System.out.println("Guide is waiting for Tourists ..."); latch.await(); System.out.println("Trip has started..."); }catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { CountDownLatch latch=new CountDownLatch(5); Guide guide =new Guide(latch); guide.start(); for (int i = 1; i <= 5; i++) { Tourist tourist =new Tourist(latch, "Tourist" + i); tourist.start(); } } }
執行結果
Guide is waiting for Tourists ...
Tourist2 has arrived
Tourist3 has arrived
Tourist4 has arrived
Tourist1 has arrived
Tourist5 has arrived
Trip has started...