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...