CountDownLatch
一个线程需要等到其他线程进行某操作时,可以使用CountDownLatch。 CountDownLatch构造方法,带有一个int类型的参数。
public CountDownLatch(int count)
当一个线程调用countDownLatch.await()时,线程会等待。直到其他线程执行 countDownLatch.countDown()。每执行一个countDown方法,初始化的count会减一,直到count=0时,等待线程才被唤醒。
假设场景顾客餐厅吃饭,需要等待做饭,炒菜,上汤都完成了,才开始吃饭。 代码:
//顾客线程
public class Customer implements Runnable {
private final CountDownLatch countDownLatch;
public Customer(CountDownLatch countDownLatch){
this.countDownLatch=countDownLatch;
}
public void run() {
System.out.println("点完菜,等待开吃");
try {
this.countDownLatch.await();
System.out.println("开饭了。。。。。。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
final CountDownLatch countDownLatch = new CountDownLatch(3);
Thread customer = new Thread(new Customer(countDownLatch));
//顾客进餐厅点菜
customer.start();
new Thread(){
@Override
public void run() {
try {
System.out.println("做饭");
}finally {
countDownLatch.countDown();
}
}
}.start();
new Thread(){
@Override
public void run() {
try {
System.out.println("炒菜");
}finally {
countDownLatch.countDown();
}
}
}.start();
new Thread(){
@Override
public void run() {
try {
System.out.println("上汤");
}finally {
countDownLatch.countDown();
}
}
}.start();
customer.join();
}
输出:
点完菜,等待开吃
做饭
炒菜
上汤
开饭了。。。。。。。。
结果正确,等待做饭,炒菜,上汤都完成了,才开始吃饭。
总结:
- countDownLatch内部通过共享锁实现
- countDown方法最好放在finally代码块中执行,防止线程永远等待
- CountDownLatch再 count减到0之后,再次执行countDown不会有影响,count不变。
- await方法有重载方法
public boolean await(long timeout, TimeUnit unit)
,等待一段时间后恢复。 - countDownLatch只能使用一次,count=0时,不能回滚再次使用。