CountDownLatch

  1. 典型应用场景:主线程启动多个子线程同时执行业务逻辑,所有子线程都执行完毕,再唤醒主线程继续执行。

  2. 例子

    public class CountDownLatchTest {/*** 计数器,初始为0*/private Integer count = 0;public Integer getCount(){return count;}/*** 执行+1操作*/public void add(){count++;}public static void main(String[] args){CountDownLatchTest test = new CountDownLatchTest();// 线程个数int threadCount = 3;//初始化工作线程的个数,并用CountDownLatch管理CountDownLatch countDownLatch = new CountDownLatch(threadCount);for(int i=0;i<threadCount;i++) {new Thread(() -> {test.add();countDownLatch.countDown();}).start();}try {//等待所有线程执行完毕,在所有线程都执行完毕之前主线程会阻塞countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(test.getCount());}
    }
    

    主线程启动了3个子线程执行add操作,等待3个子线程都执行完毕了,主线程继续执行打印最终的执行结果为:3。

  3. 具体实现原理:

    public class CountDownLatch {//继承于AQS的同步器private static final class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = 4982264981922014374L;//有参构造函数,count记录了共享资源的个数Sync(int count) {setState(count);}//获取当前共享资源的个数int getCount() {return getState();}/*** 尝试以共享方式获取资源* @return 1表示获取成功,-1表示获取失败*/protected int tryAcquireShared(int acquires) {//如果当前资源个数为0,则表示获取成功,否则表示失败return (getState() == 0) ? 1 : -1;}/*** 尝试以共享方式释放资源* @return true表示释放成功,false表示释放失败*/protected boolean tryReleaseShared(int releases) {// 对当前资源执行-1操作for (;;) {int c = getState();if (c == 0)return false;int nextc = c-1;//CAS更新资源个数,CAS失败表示有其他线程竞争,此时需要重试if (compareAndSetState(c, nextc))//执行-1操作后,如果资源个数为0,则表示释放成功return nextc == 0;}}}private final Sync sync;//有参构造函数,可以看到CountDownLatch中禁用了默认构造函数,意味着必须传入资源个数public CountDownLatch(int count) {if (count < 0) throw new IllegalArgumentException("count < 0");this.sync = new Sync(count);}//等待操作,此方法会使调用线程阻塞,直到其他调用countdown的方法都执行完毕public void await() throws InterruptedException {//此处调用的是AQS的acquireSharedInterruptibly方法,下文会具体分析sync.acquireSharedInterruptibly(1);}//和await()类似,但是有一个等待的超时时间,过了超时时间会自动取消等待public boolean await(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}//将state的值-1,当getState()==0时,会唤醒调用await()线程public void countDown() {//调用AQS的releaseShared方法,下文会具体分析sync.releaseShared(1);}//获取当前资源的个数public long getCount() {return sync.getCount();}
    }
    
  4. CountDownLatch中用到的AQS的核心方法:

    public final void acquireSharedInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();//尝试获取资源失败(tryAcquireShared的返回值<0),会将当前线程阻塞并排队等待if (tryAcquireShared(arg) < 0)//该方法会将当前线程阻塞,并放入AQS的同步队列等待,此处不再分析doAcquireSharedInterruptibly(arg);
    }//释放共享资源
    public final boolean releaseShared(int arg) {//尝试释放共享资源成功时(此处要结合CountDownLatch提供的tryReleaseShared方法理解),进行具体的释放操作if (tryReleaseShared(arg)) {//AQS提供的执行具体的资源释放操作,会唤醒调用await()方法的线程doReleaseShared();return true;}return false;
    }
    
  5. 总结:CountDownLatch使用AQS的state变量作为状态计数器,执行countdown操作的线程会将计数器减1,当前计数器的值为0时(getState()==0),会唤醒执行await操作的线程继续执行。

Java并发编程之CountDownLatch闭锁相关推荐

  1. Java并发编程之CountDownLatch(闭锁)使用详解

    package com.zhangxueliang.day_20191108;import java.util.concurrent.CountDownLatch;/*** 计算多线程的运行时间* @ ...

  2. Java并发编程之CountDownLatch、CyclicBarrier和Semaphore

    前言 本文为对CountDownLatch.CyclicBarrier.Semaphore的整理使用 CountDownLatch CountDownLatch类位于java.util.concurr ...

  3. Java并发编程之CountDownLatch源码解析

    一.导语 最近在学习并发编程原理,所以准备整理一下自己学到的知识,先写一篇CountDownLatch的源码分析,之后希望可以慢慢写完整个并发编程. 二.什么是CountDownLatch Count ...

  4. Java并发编程之CountDownLatch/CyclicBarrierDemo/SemaphoreDemo详解

    CountDownLatch详解 什么是CountDownLatch? 代码说明一 :班长锁门 代码说明二:秦国统一六国 什么是CyclicBarrierDemo? 代码说明一:集齐7个龙珠,召唤神龙 ...

  5. Java并发编程之CountDownLatch

    目录 一.概述 二.CountDownLatch与join的异同 三.源码解析 3.1.await方法源码解析 3.2.downCount方法源码解析 一.概述 作用:可以用来确保某些活动直到其他活动 ...

  6. Java并发编程之CyclicBarrier详解

    简介 栅栏类似于闭锁,它能阻塞一组线程直到某个事件的发生.栅栏与闭锁的关键区别在于,所有的线程必须同时到达栅栏位置,才能继续执行.闭锁用于等待事件,而栅栏用于等待其他线程. CyclicBarrier ...

  7. zbb20180929 thread java并发编程之Condition

    java并发编程之Condition 引言 在java中,对于任意一个java对象,它都拥有一组定义在java.lang.Object上监视器方法,包括wait(),wait(long timeout ...

  8. java并发编程之4——Java锁分解锁分段技术

    转载自 java并发编程之4--Java锁分解锁分段技术 并发编程的所有问题,最后都转换成了,"有状态bean"的状态的同步与互斥修改问题.而最后提出的解决"有状态bea ...

  9. Java 并发编程之美:并发编程高级篇之一-chat

    借用 Java 并发编程实践中的话:编写正确的程序并不容易,而编写正常的并发程序就更难了.相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作 ...

最新文章

  1. assert self.binded
  2. 7、ShardingSphere 之 Sharding-Proxy
  3. 5.3 递归最小二乘法
  4. 16 张图解带你掌握一致性哈希算法
  5. 关于Element UI中select组件中遇到的问题
  6. Android 系统(123)---MTK android 常用修改点
  7. 数学打比方(函数和卷积)
  8. c++ string详解 assign
  9. Doris之拦截规则 sql黑名单
  10. NYOJ题目325-zb的生日
  11. config system丢失
  12. Postgresql去掉某个字段多余的空格
  13. mysql百万数据迁移_Mysql百万级数据迁移实战笔记
  14. 机器学习练习----神经网络的标准BP算法(误差逆传播算法)
  15. MySQL 中文字段排序问题(根据中文拼音排序)
  16. android浏览器400错误代码,console.log在谷歌浏览器和Android浏览器的本地代码错误...
  17. Python实现猫脸识别 | 喵主子福利
  18. Power bi 4.3 子弹图
  19. 谈IBM的转型与人工智能开发
  20. ffmpeg多路视频拼接

热门文章

  1. 微信小程序运行的底层逻辑
  2. Python数据挖掘学习笔记】九.回归模型LinearRegression简单分析氧化物数据
  3. 谷歌Pixel 6系列手机发布会官宣定档 10月19日发布
  4. 特斯拉股价,真的“血崩”!
  5. iQOO Neo5入网:搭载双电芯方案 标配66W快充
  6. iPhone 12 Mini曝光:售价5000内、电池容量不忍看
  7. 微信品牌小程序开启公测 认证通过即享专属产品能力
  8. 电影院今日复业!20部影片上映,票房预售超百万
  9. 京东股价创新高:市值首次突破千亿美元 !
  10. 王者归来!华为P40 Pro渲染图曝光:后置矩阵徕卡五摄模组