什么是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,至于实现原理的,后续的内容会写。

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

相关推荐
小蒜学长1 小时前
基于SpringBoot和Vue的低卡食品销售系统的设计与实现(代码+数据库+LW)
java·后端·springboot·健康管理·低卡食品销售系统
CRMEB系统商城1 小时前
前后端技术栈全面换代!CRMEB 多商户(Java)v3.0更新预告
java·开发语言·小程序·php
白起那么早1 小时前
idea 插件-把数据库的表画出来
数据库·后端·intellij idea
蓝宝石的傻话2 小时前
onvif-go(mickeyzzc/onvif-go v2)完整参考手册:从建工程到写出自己的 NVR 接入
开发语言·后端·golang
喵个咪2 小时前
GoWind Admin|风行 — 开箱即用的企业级全栈中后台框架:AI 模块
后端·go·ai编程
喵个咪2 小时前
GoWind Admin|风行 — 开箱即用的企业级全栈中后台框架:AK/SK 机器凭证
后端·安全·架构
雾喔2 小时前
近日总结 & 面试经验
面试·职场和发展
Sayai2 小时前
Neo4j 内嵌模式(Embedded)实战:Java 嵌入式 vs 服务端部署的写入性能对比与 GC 调优
java·开发语言·性能优化·neo4j·图数据库
木头科技2 小时前
AI 工程化第四篇】Spring AI Agent 线上可观测实战:Token 成本、调用链、工具耗时、RAG 命中率怎么监控
java·人工智能·spring