CountDownLatch用法以及原理简介

154 阅读3分钟

一、CountDownLatch简介

CountDownLatch是java中的同步工具类,代码结构相对简单,基本原理如下:
1.初始化new CountDownLatch()的时候通过AQS添加一定数量的许可.
2.await()方法通过自旋判断AQS的状态是否为0选择是否使当前线程等待
3.countDown()方法通过自旋+Compare-And-Swap对比减少1个许可,最终减少到0后 await()方法自旋判断AQS状态为0,释放等待。
具体代码可自行查看JDK源码

二、CountDownLatch基本使用场景

1.多个线程等待用法
用LOL举例,比如中单正在对线,队友埋伏在草丛中,等待中单发放指令,队友齐上,击败敌方英雄

public static void main(String[] args) throws InterruptedException {
    CountDownLatch countDownLatch = new CountDownLatch(1);
    for (int i = 1; i < 5; i++) {
        int finalI = i;
        new Thread(()->{
            try {
                log.info("队员"+finalI+"已在中路左侧草丛准备好");
                countDownLatch.await();
                log.info("队员"+finalI+"对敌方英雄造成50点伤害");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();
    }
    log.info("对线的中单诱敌中");
    Thread.sleep(3000);
    log.info("中单已诱敌深入,发放开打指令,兄弟们,上!");
    countDownLatch.countDown();
    log.info("中单对敌方英雄造成500点伤害");
}

日志输出:

22:57:31.904 [Thread-0] INFO - 队员1已在中路左侧草丛准备好

22:57:31.904 [Thread-1] INFO - 队员2已在中路左侧草丛准备好

22:57:31.904 [Thread-3] INFO - 队员4已在中路左侧草丛准备好

22:57:31.904 [main] INFO - 对线的中单诱敌中

22:57:31.904 [Thread-2] INFO - 队员3已在中路左侧草丛准备好

22:57:34.911 [main] INFO - 中单已诱敌深入,发放开打指令,兄弟们,上!

22:57:34.912 [main] INFO - 中单对敌方英雄造成500点伤害

22:57:34.912 [Thread-0] INFO - 队员1对敌方英雄造成50点伤害

22:57:34.912 [Thread-1] INFO - 队员2对敌方英雄造成50点伤害

22:57:34.912 [Thread-3] INFO - 队员4对敌方英雄造成50点伤害

22:57:34.912 [Thread-2] INFO - 队员3对敌方英雄造成50点伤害

2.单线程等待用法
用LOL举例,比如你正在对线,技能都在冷却中,这个时候肯定不能上前和敌方英雄作战,等待所有技能冷却完毕,敌方英雄血量已到斩杀线,四个技能齐上,击败敌方英雄

public static void main(String[] args) throws InterruptedException {
    CountDownLatch countDownLatch = new CountDownLatch(4);
    for (int i = 1; i < 5; i++) {
        int finalI = i;
        new Thread(() -> {
            try {
                log.info("技能" + finalI + "冷却中");
                Thread.sleep(new Random().nextInt(3000));
                log.info("技能" + finalI + "已重置");
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();
    }
    log.info("等待技能重置中");
    countDownLatch.await();
    log.info("敌方英雄已到斩杀线,四个技能齐上,击杀了敌方英雄!");
}

日志输出:

22:05:55.385 [Thread-3] INFO - 技能4冷却中

22:05:55.385 [main] INFO - 等待技能重置中

22:05:55.385 [Thread-0] INFO - 技能1冷却中

22:05:55.385 [Thread-2] INFO - 技能3冷却中

22:05:55.385 [Thread-1] INFO - 技能2冷却中

22:05:55.824 [Thread-0] INFO - 技能1已重置

22:05:55.963 [Thread-3] INFO - 技能4已重置

22:05:57.000 [Thread-2] INFO - 技能3已重置

22:05:57.535 [Thread-1] INFO - 技能2已重置

22:05:57.536 [main] INFO - 敌方英雄已到斩杀线,四个技能齐上,击杀了敌方英雄!