多线程基础系列之 CountDownLatch

📒一、线程工具

背景故事

🔊 很久以前面试大厂,被面试官问到有没有使用过 CountDownLatch,我说使用过;面试官追问,那你可以说一下具体使用场景吗,脑袋一懵,竟然答不上来。是的,我背的八股文已经忘了,之前我也确实没有使用过。

最近碰到有一个同事错误地使用了 CountdownLatch,不由的想谈一谈 CountdownLatch 的使用。

官方解释

同步工具类,允许一个或多个线程一直等待,直到其他线程运行完成后再执行 (A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.)

单线程等待执行 多线程同步等待执行

有了上面理解,接下来再看看应用场景

📚二、应用场景

举几个实际应用用到的例子,不会使用 CountDownLatch 的请抄作业了。

单线程等

RPC 远程调用场景

  1. RPC 底层通信调用是一个异步行为。
  2. 在调用之前设置 CountDownLatch
  3. 异步调用结束后,回调 countDown 方法
  4. 这个时候主方法继续向下执行
Java 复制代码
// 1. 设置  CountDownLatch
final CountDownLatch latch = new CountDownLatch(1);
final RpcResult result = new RpcResult();

// 2.发起远程 RPC 调用。 RPC 返回结果, 触发 callback 调用,修改 CountDownLatch
remoteInvoke(getHost(requestLine), request, new CallBack(timeout) {
    @Override
    public void handled(Response response) throws Exception {
        try {
            Response.Status status = response.startLine();
            byte[] bytes = response.body().bytes();
            ......
            result.setStateCode(status.code());
        } catch (Exception e) {
            result.setCause(t);
        } finally {
            // 必须放在 final里面
            latch.countDown();
        }
    }
});

可以把 remoteInvoke 理解为线程操作。

很多框架的源码启动类,都会有异步加载过程并同步等待,就是下面这个模板代码,试着再你的工程中用一用。

Java 复制代码
  final CountDownLatch launchLatch = new CountDownLatch(1);
  Thread launcherThread = new Thread(() -> {
      try {
        .......
      } finally {
          launchLatch.countDown();
      }
  });
   .....
 latch.await(timeout, TimeUnit.MILLISECONDS);

多线程等

多线程等待的场景,比如并发下载,并发查询等等

Java 复制代码
final CountDownLatch latch = new CountDownLatch(nTasks);
for (int i = 0; i < nTasks; ++i) {
    executorService.submit(
            new Runnable() {
                @Override
                public void run() {
                    try {
                        // 业务操作 method
                    } finally {
                        latch.countDown();
                    } 
                }
            });
}
latch.await();

补充场景

  • 启动类,异步加载资源
  • 源码中的注释也有两个详细的例子

📑三、其他补充

源码浅析

内部实现一个 AbstractQueuedSynchronizer(AQS 队列同步器),源码并不多,主要,通过改变 private volatile int state 值来实现线程之间的协助。 state 不为 0 继续等待,为 0 向下执行。调用 countDown 则 state 减一

学会慢慢的把这些工具类应用到你的工程里面,别再做 CRUD boy 了。

同类工具

  1. Thread#join
  2. Future#get
  3. CompletableFuture

纸上得来终觉浅,绝知此事要躬行.

相关推荐
立莹Sir20 小时前
Spring Bean 生命周期详解
java·python·spring
uElY ITER20 小时前
Spring全家桶简介
java·后端·spring
lay_liu1 天前
springboot 文件下载
java·spring boot·后端
Flittly1 天前
【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库
java·笔记·spring·ai·springboot
workflower1 天前
AI制造-推荐初始步骤
java·开发语言·人工智能·软件工程·制造·需求分析·软件需求
ACGkaka_1 天前
SimpleDateFormat 线程安全问题及修复方案
java·jvm·安全
leo_messi941 天前
多线程(五) -- 并发工具(二) -- J.U.C并发包(八) -- CompletableFuture组合式异步编程
android·java·c语言
m0_380113841 天前
SpringBoot创建动态定时任务的几种方式
java·spring boot·spring
Gofarlic_OMS1 天前
SolidEdge专业许可证管理工具选型关键评估标准
java·大数据·运维·服务器·人工智能