什么是CountDownLatch?

像我们程序员呢,经常会去参加需求评审,一般来说,都是开发、测试、产品经理都到齐了才能开始的,会议的负责人是产品经理。这里就有「等」的问题,等人齐了,就开始开会,人没有齐,会议不会开。

在程序的世界里,这种「人齐了才能干活」的场景同样也是随处可见的。比如说,一个电商系统的商品聚合详情页,需要同时去调用商品基础信息服务、库存服务和优惠券服务。为了提高响应速度,可以开启3个并发线程去分别拉取数据。但最后拼装数据返回给前端时,主线程必须等这3个子任务全部完成,任何一个数据没拿到,页面都无法完整渲染。

那么,主程序怎么知道这3个线程到底有没有到齐呢?

这时,我们就需要一位会议主持人(主线程)和签到员(同步工具CountDownLatch)。

注意,签到员才是CountDownLatch。主线程不是,CountDownLatch是用来协调线程的,在这里就是要协调主线程和子线程(协同的线程)。

为了方便大家理解和做好映射,我列一个表格,把上面需求评审会的场景跟CountDownLatch映射起来。

需求会议中的场景 Java中的代码逻辑
签到员拿出一张纸,上面写着应到3人 CountDownLatch latch = new CountDownLatch(3);
开发/测试/产品赶到会议室,向签到员报到 每个子线程完成任务后,调用latch.countDown()(计数器 -1)
主持人问签到员:人齐了吗? 签到员说:还没,你先坐着等。 主线程调用latch.await(),且被阻塞挂起
当最后一个人报到,签到员看表:还差0人,人全齐了! 计数器扣减到0
签到员叫醒主持人:可以开会了 CountDownLatch唤醒被阻塞的主线程,await()方法返回,主线程继续往下执行

好,下面我们将上面的场景,用java 17来实现。

用代码模拟

对应到代码里:主持人就是主线程,签到员就是一个CountDownLatch,开发、测试、产品经理是三个参会线程。完整代码如下:

java 复制代码
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;

public class MeetingDemo {

    public static void main(String[] args) throws Exception {
        // 签到表:应到3人,开发、测试、产品经理各一个
        CountDownLatch latch = new CountDownLatch(3);
        String[] roles = {"开发", "测试", "产品经理"};

        // 三个参会人各起一个线程,从工位走到会议室
        for (String role : roles) {
            new Thread(() -> {
                try {
                    // 走路耗时不一样,300到800毫秒不等
                    Thread.sleep(ThreadLocalRandom.current().nextInt(300, 800));
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                System.out.println(role + "到了会议室");
                // 人到就向签到员报到,签到表上的名字划掉一个
                latch.countDown();
            }).start();
        }

        // 主持人(主线程)在签到员这里等,人没齐就停着
        latch.await();
        System.out.println("人到齐了,会议开始");
    }
}

运行结果如下:

text 复制代码
产品经理到了会议室
开发到了会议室
测试到了会议室
人到齐了,会议开始

三个参会人各是一个线程,走路的耗时不一样,所以每遍输出里,到达的顺序都不一样。每个人到会议室后做的事都是一样的:向签到员报到,countDown()把签到表上的名字划掉一个。主持人(主线程)到了就await(),在签到员这里等,名字没划完就一直停着。

三个名字全部划掉,计数从3减到0,await()返回,对应的就是表格里的最后一行:签到员叫醒主持人,会议开始。

业务代码里使用CountDownLatch的场景

我这边在生产环境里,是经常使用CountDownLatch的,下面我列其中一个场景,批量翻译。

由于我这边一直是从事连锁店行业的,因此相关的业务场景,也是连锁店相关的。

我们当时的门店是开到全世界的,日本,美国,澳门,香港等,都在开店,因此相关的语言是做翻译的。

当运营点一下一键翻译,一批文案要调外部翻译服务,翻成多个语种,单次调用几百毫秒。因此就做并发翻译,主线程要等这批全部翻完,才把结果组装好返回到页面。

凡是主线程需要等多个子线程干完后,才能开始的,你就可以使用CountDownLatch这个同步工具。

这篇内容的主要目的,就是让你了解什么是CountDownLatch,至于实现原理的,后续的内容会写。

感谢您的阅读,希望这篇文章可以帮助到你。

相关推荐
Wang's Blog29 分钟前
Java 项目实战: 交友项目 - FastDFS:入门案例
java·开发语言·交友
一只爱撸猫的程序猿32 分钟前
我看着一个 AI 引擎在 14 天里,从"记忆"走进了"搜索"
人工智能·后端·架构
apcipot_rain1 小时前
C++转Java日记(03)
java·开发语言·c++
皮皮林5511 小时前
Java实现微信扫码登录
java
陈随易3 小时前
纯 Go 写的 JS 引擎,跑分超过了 C 语言的 QuickJS
前端·后端·程序员
Yyyyyy~4 小时前
【Java】Day4Web基础知识
java·spring boot
卷无止境4 小时前
RAGFlow 项目全景报告:从文档解析引擎到 Agent 原生数据库
后端·python
小Z先生5 小时前
我用 Go + 系统 WebView 写了个纯本地 Postman:不装 Electron、不连云端
后端·github
IT_陈寒5 小时前
Redis连接池泄漏那次,我差点把生产环境搞崩了
前端·人工智能·后端
灿飞屋5 小时前
Kotlin与Java虚拟机三:控制流
android·java·开发语言·后端·python·kotlin·安卓