CountDownLatch:并发流程控制工具;倒数门闩;
例子:购物拼团;游乐园坐过山车排队,人满发车;
流程:倒数结束之前,一直处于等待状态,直到倒计时结束了,此线程才继续工作
主要方法介绍:
CountDownLatch(int count):仅有一个构造函数,参数count为需要倒数的数值
await():调用wait()方法的线程会被挂起,它会等待直到count值为0才继续执行
countDown():将count值减1,直到为0时,等待的线程会被唤起
两个典型用法:多等一和一等多 两者结合
用法一: 一个线程等待多个线程都执行完毕,再继续自己的工作; 例子:工厂5个质检员,只有都认为该产品合格,才能通过
用法二:多个线程等待某一个线程的信号,同时开始执行; 例子:跑步运动员等待发令员统一起跑
注意点:
扩展用法:多个线程等多个线程完成执行后,再同时执行
CountDownLatch是不能够重用的,如果需要重新计时,可以考虑使用CycliBarrier或者创建新的CountDownLatch实例
// 倒数门闩演示:工厂中,质检,5个工人检查,所有人都认为通过,才通过;
public class CountDownLatchDemo1 {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(5);
ExecutorService service = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
final int finalI = i;
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep((long) (Math.random()*10000));
System.out.println("No."+ finalI +"完成了检查");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
latch.countDown();
}
}
};
service.submit(runnable);
}
System.out.println("5个工人检查中。。。。。。");
latch.await();
System.out.println("工人检查完毕!!!!!!");
service.shutdown();
}
}
// 模拟百米跑步,5名选手,只等裁判员一声令下,所有人同时跑步;
// 综合1和2 多等一及一等多情景:5名选手,只等裁判员一声令下,所有人同时跑步;然后等5个运动员都到达终点,就打印所有人到达终点,比赛结束
public class CountDownLatchDemo1And2 {
public static void main(String[] args) throws InterruptedException {
// count 真正的含义是 有几个人倒数,因为裁判员只有一个,所以只有一个倒数
CountDownLatch begin = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(5);
ExecutorService service = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
final int finalI = i + 1;
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("No." + finalI + "准备完毕,等待发令枪");
begin.await();
System.out.println("No." + finalI + "开始跑步了");
Thread.sleep((long) (Math.random() * 10000));
System.out.println("No." + finalI + "跑到终点");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
end.countDown();
}
}
};
service.submit(runnable);
}
// 裁判员检查发令枪。。。
Thread.sleep(3000);
System.out.println("发令枪响,比赛开始");
begin.countDown();
end.await();
System.out.println("所有人到达终点,比赛结束");
service.shutdown();
}
}