文章目录

  • CountDownLatch是什么
  • 核心方法
    • 构造方法
    • 常用的其他三个方法
  • 使用案例

CountDownLatch是什么

countDownLatch是在java1.5被引入,可以翻译为计数器。主要用于等待多个线程一起执行完成后继续下一步,Thread.join()有点类似

核心方法

构造方法

CountDownLatch 值提供了一个构造方法,传入一个计数器的值

常用的其他三个方法

这里看不懂可以直接去看后面案例

//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public void await() throws InterruptedException {//调用AQS的acquireSharedInterruptibly()方法sync.acquireSharedInterruptibly(1);}
// 和上面方法一样,添加了一个超时时间,到超时时间及时conut没到0调用线程也继续执行
public boolean await(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}
// 计数器count值减1
public void countDown() {//调用AQS的释放共享锁方法sync.releaseShared(1);}

可以看到 这几个方法都是直接 调用 sync这个类的方法,这个sync是个什么类呢

这里可以看到 Sync 是 CountDownLatch 的一个内部类,而Sync 继承了AbstractQueuedSynchronizer,上面的 acquireSharedInterruptibly 都是直接调用AbstractQueuedSynchronizer父类的acquireSharedInterruptibly方法

而最终调用的是AbstractQueuedSynchronizer的 doAcquireSharedInterruptibly方法

private void doAcquireSharedInterruptibly(int arg)throws InterruptedException {// 添加节点至等待队列final Node node = addWaiter(Node.SHARED);boolean failed = true;try {for (;;) {// 获取node的前驱节点final Node p = node.predecessor();// 如果前驱节点为头结点if (p == head) {/** 试图在共享模式下获取对象状态,tryAcquireShared为抽象方法供子类实现,*   Sync就实现了该方法,很简单的判断一个state状态是否为0* ,state被volatile修饰,保证多线程见的可见性,同时不适用锁提升性能**/int r = tryAcquireShared(arg);// 获取成功if (r >= 0) {//设置队列头,并检查后来者是否在共享模式下等待,如果是,则传播setHeadAndPropagate(node, r);p.next = null; // help GCfailed = false;return;}}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);}}

使用案例

这里案例我们基于RocketMQ的源码使用方式来模拟

这里可以看到Broker 注册到NamerServer的时候就使用了CountDownLatch,不了解RocketMq也可以简单的理解为,我一个系统需要RPC调用多个三方系统发短信,而网络IO请求相对耗时,所以我们使用多线程去请求,同时要保证所有短信发送完成我们才能执行后续代码返回发送成功

public static void main(String[] args) {// 使用Java自带线程池,生产环境不推荐使用,这里演示demo为了简单ExecutorService threadPool = Executors.newFixedThreadPool(5);// 需要发送 20个短信CountDownLatch countDownLatch = new CountDownLatch(20);AtomicInteger count = new AtomicInteger();for (int i = 0; i < 20; i++) {threadPool.execute(() -> {// 模拟发送短信System.out.println("发送短信");// 假装耗时2stry {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}// 发送短信完成System.out.println("-----------发送短信数量:" + count.incrementAndGet());countDownLatch.countDown();});}try {countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("所有短信发送完成");}

执行结果:

发送短信
发送短信
发送短信
发送短信
发送短信
-----------发送短信数量:1
-----------发送短信数量:5
-----------发送短信数量:4
-----------发送短信数量:3
发送短信
发送短信
-----------发送短信数量:2
发送短信
发送短信
发送短信
-----------发送短信数量:7
-----------发送短信数量:9
发送短信
-----------发送短信数量:10
-----------发送短信数量:8
-----------发送短信数量:6
发送短信
发送短信
发送短信
发送短信
-----------发送短信数量:13
-----------发送短信数量:12
-----------发送短信数量:14
-----------发送短信数量:11
-----------发送短信数量:15
发送短信
发送短信
发送短信
发送短信
发送短信
-----------发送短信数量:17
-----------发送短信数量:18
-----------发送短信数量:20
-----------发送短信数量:16
-----------发送短信数量:19
所有短信发送完成Process finished with exit code -1

多线程同步器之CountDownLatch相关推荐

  1. Android 价值千万java多线程同步 lt;五CountDownLatch(计数器)和Semaphore(信号量)

    1).Android 价值千万   java线程专题:Wait&notify&join&Yield http://blog.csdn.net/whb20081815/artic ...

  2. 聊天室软件源码开发中,该如何实现多线程同步?

    问题背景 在聊天室软件源码开发中,需执行多线程任务:任务1.任务2并行执行:等全部执行完成后,执行任务3. // 每个 任务 通过 sleep 模拟耗时 val task1: () -> Str ...

  3. python多线程读取文件的问题_Python多线程同步---文件读写控制方法

    1.实现文件读写的文件ltz_schedule_times.py #! /usr/bin/env python #coding=utf-8 import os def ReadTimes(): res ...

  4. 【转】windows平台多线程同步之Mutex的应用

    线程组成: 线程的内核对象,操作系统用来管理该线程的数据结构. 线程堆栈,它用于维护线程在执行代码时需要的所有参数和局部变量.   操作系统为每一个运行线程安排一定的CPU时间 -- 时间片.系统通过 ...

  5. java线程条件变量_多线程同步条件变量(转载)

    最近看<UNIX环境高级编程>多线程同步,看到他举例说条件变量pthread_cond_t怎么用,愣是没有看懂,只好在网上找了份代码,跑了跑,才弄明白 #include #include ...

  6. MFC多线程同步互斥

    MFC多线程同步互斥[转载] http://blog.sina.com.cn/s/blog_62d15fb601017dhn.html https://www.cnblogs.com/zhanghu5 ...

  7. 34 多线程同步之Event

    事件用于线程之间的通信.一个线程发出一个信号,其他一个或多个线程等待,调用Event对象的wait方法,线程则会阻塞等待,直到别的线程set之后才会被唤醒. [示例 1]使用Event实现多线程同步 ...

  8. 线程同步锁 java_java多线程同步之重入锁,详细解析

    上次已经为大家介绍过java多线程同步,Volatile详解的主要内容了.今天再来为大家介绍一些相关的内容,也就是java多线程同步之重入锁,一起来了解一下吧. 使用重入锁实现线程同步 在JavaSE ...

  9. Servlet基础(三) Servlet的多线程同步问题

    Servlet基础(三) Servlet的多线程同步问题 Servlet/JSP技术和ASP.PHP等相比,由于其多线程运行而具有很高的执行效率. 由于Servlet/JSP默认是以多线程模式执行的, ...

最新文章

  1. authc过滤器 shiro_shrio 权限管理filterChainDefinitions过滤器配置
  2. 程序员的灯下黑:不要忘记你的目标
  3. navicat premium 连接oracle_Navicat Preminm连接oracle时闪退问题解决
  4. Java NIO示例:多人网络聊天室
  5. python爬取的信息条数比页面显示多_Python爬取分析北京二手房数据?数据结果真的太吓人了...
  6. 查询排序_MySQL使用UNION连接两个查询排序失效
  7. 谷歌入职邮件_为什么我全职学习了8个月以接受Google采访
  8. 王道考研 计算机网络1 计算机网络概念,组成,功能和分类
  9. hibernate保存mysql乱码_hibernate保存数据到mysql时的中文乱码问题
  10. CNI portmap插件实现源码分析
  11. (转)Spring的三种实例化Bean的方式
  12. linux 用户权限 数字,几个linux命令之用户权限相关命令
  13. 帝国理工 计算机 金融和管理,计算机毕业生同样研读帝国理工金融工程
  14. js base64图片太大_JS实现base64图片下载 简易方法
  15. google嗅探(简洁实用版)
  16. PostgreSQL之日期字段统一加一天
  17. Linux磁盘管理工具RAID、Parted
  18. C# winform 生成APP
  19. 华为实验28-WAN接入配置
  20. 游戏语音聊天系统完美运营源码,附详尽视频教程

热门文章

  1. 计算机硬件培训ttp,通信新技术优秀教学平台(TTP).doc
  2. 解决org.apache.zookeeper.KeeperException$UnimplementedException:KeeperErrorCode = Unimplemented for /S
  3. 我在乐视9年,亲眼看贾跃亭一步步走向失控
  4. Element UI表格拖拽(vue中) —— 行拖拽、列拖拽
  5. Java实现字符串反转的几种方法
  6. 求助:大文件mp4恢复
  7. C语言入门最基础教学(编译器下载)
  8. Java 中的比较器
  9. linux vi 报错 E37: No write since last change (add to override)
  10. c++中static的用法详解