CountDownLatch
1、并发流程控制
倒数门闩
例如:100米冲刺比赛,参赛者都准备好后,等裁判一声令下,全力冲出。
流程:倒数结束之前,一直处于等待状态,直到倒计时结束了,此线程才继续工作。
2、类的主要方法介绍
CountDownLatch(int count):仅有一个构造函数,参数 count 为需要倒数的数值。
await():调用 await() 方法的线程会被挂起,它会等待直到 count 值为 0 才继续执行。
countDown():将 count 值减一,直到为 0 时,等待的线程会被唤起。
初始化为 3 个计数器,Ta 等待倒计时,然后其他线程 T1、T2、T3 分别执行 countDown() ,到最后为 0 Ta 被唤醒,然后执行其他代码。
3、一等多
/** * @description 在工厂中,质检,5个人检查,所有人都认为通过,才通过 * @author: hq * @create: 2022-08-20 14:54 **/ public class CountDownLatchDemo1 { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(5); ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 5; i++) { final int no = i + 1; Runnable runnable = new Runnable() { @Override public void run() { try { Thread.sleep((long) (Math.random() * 10000L)); System.out.println("No." + no + "完成工作"); } catch (InterruptedException e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } } }; executorService.execute(runnable); } System.out.println("等待5人检查完。。。"); countDownLatch.await(); System.out.println("所有人都完成工作"); } }
4、多等一
/** * @description 模拟100米跑步,5名选手都准备好了,就等裁判员法令。同时跑出 * @author: hq * @create: 2022-08-20 15:05 **/ public class CountDownLatchDemo2 { public static void main(String[] args) throws InterruptedException { CountDownLatch begin = new CountDownLatch(1); ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 5; i++) { final int no = i + 1; Runnable runnable = new Runnable() { @Override public void run() { System.out.println("No." + no + "准备完毕,等待发令"); try { begin.await(); System.out.println("No." + no + "开始跑步"); } catch (InterruptedException e) { e.printStackTrace(); } } }; executorService.execute(runnable); } Thread.sleep(5000); System.out.println("发令,比赛开始"); begin.countDown(); } }
5、将一等多,多等一结合在一起
/** * @description * @author: hq * @create: 2022-08-20 15:12 **/ public class CountDownLatchDemo3 { public static void main(String[] args) throws InterruptedException { CountDownLatch end = new CountDownLatch(5); CountDownLatch begin = new CountDownLatch(1); ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 5; i++) { final int no = i + 1; executorService.execute(() -> { System.out.println("No." + no + "准备好了"); try { begin.await(); // 一声令下,开始比赛 Thread.sleep((long) (Math.random() * 10000)); System.out.println("No." + no + "冲过终点"); end.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }); } //裁判检查情况 Thread.sleep(2000); // 一声令下 begin.countDown(); System.out.println("一声令下,比赛开始"); end.await(); System.out.println("所有人冲过终点,比赛结束"); } }
6、 注意点
CountDownLatch 不能回滚重置,重复使用。