CountDownLatch用法详解

CountDownLatch使用场景

线程计数器 用于线程执行任务,计数 等待线程结束

用法一: 等待所有的事情都做完

//程序计数器CountDownLatch countDownLatch = new CountDownLatch(10000);//2个线程ExecutorService executorService = Executors.newFixedThreadPool(2);AtomicInteger count = new AtomicInteger(0);for (int i = 0; i < 10000; i++) {executorService.submit(() -> {count.getAndIncrement();//自增System.out.println(Thread.currentThread().getName() + " : " + count.get());countDownLatch.countDown();});}//线程池 等待10sexecutorService.awaitTermination(10, TimeUnit.SECONDS);//关闭线程 其实是将线程状态设置为中断标志  必须等待所有线程处理完任务,才能完全关闭executorService.shutdown();//必须等待两个线程执行完   会一直等待下去,当然也可以设置指定时间等待超时 await(timeout);countDownLatch.await();}

始终是2个线程在做事情,等2个线程做完事情才会停止下来。

用法二:假设2个线程做事情,刚开始并行做事情,等一个执行完成之后,另一个才能执行(实际还是计数)

//程序计数器CountDownLatch countDownLatch = new CountDownLatch(1);Thread thread1 =new Thread(()->{System.out.println(" ---------------- 1  准备 ---------------- ");try {countDownLatch.await();System.out.println(" ---------------- 1  finsh  ---------------- ");} catch (InterruptedException e) {e.printStackTrace();}});thread1.start();Thread thread2 = new Thread(() -> {System.out.println(" ---------------- 2  准备 ---------------- ");try {Thread.sleep(1_000);System.out.println(" ---------------- 异步做事情  ---------------- ");} catch (InterruptedException e) {e.printStackTrace();}finally {countDownLatch.countDown();}});thread2.start();//main 在等main 结束  死循环Thread.currentThread().join();

刚开始一起在准备状态,然后分开做事情

用法三:退出条件

中断一个线程 count 到0

        //程序计数器CountDownLatch countDownLatch = new CountDownLatch(1);Thread thread = Thread.currentThread();Thread thread1 = new Thread(() -> {try {Thread.sleep(10_000);} catch (InterruptedException e) {e.printStackTrace();}// 1 中断条件1countDownLatch.countDown();});thread1.start();countDownLatch.await();System.out.println(" ----------------- ");}

等待时间中断

        //程序计数器CountDownLatch countDownLatch = new CountDownLatch(1);Thread thread = Thread.currentThread();Thread thread1 = new Thread(() -> {try {Thread.sleep(10_000);} catch (InterruptedException e) {e.printStackTrace();}});thread1.start();//2 中断条件3countDownLatch.await(5, TimeUnit.SECONDS);System.out.println(" ----------------- ");}

就中断条件而言: 当前还可以父线程中断

//程序计数器Thread thread1 = new Thread(() -> {try {Thread.sleep(10_000);} catch (InterruptedException e) {e.printStackTrace();}// 中断条件3thread.interrupt();});thread1.start();System.out.println(" ----------------- ");

用法四: 封装结束完后通知事件

封装结束完后通知事件 参考 CyclicBarrier 通知

public class CountDownLatchTest4 extends CountDownLatch {private Runnable runnable;public CountDownLatchTest4(int count, Runnable runnable) {super(count);this.runnable = runnable;}@Overridepublic void countDown() {super.countDown();if (super.getCount()==0){runnable.run();}}public static void main(String[] args) throws InterruptedException {//程序计数器CountDownLatchTest4 countDownLatch = new CountDownLatchTest4(1,()->{System.out.println(" 计数结束 .... ");});Thread thread1 = new Thread(() -> {try {Thread.sleep(2_000);countDownLatch.countDown();System.out.println(" thread 1 do something ");} catch (InterruptedException e) {e.printStackTrace();}});Thread thread2 = new Thread(() -> {try {Thread.sleep(1_000);System.out.println(" thread 2 do something ");countDownLatch.countDown();} catch (InterruptedException e) {e.printStackTrace();}});thread1.start();thread2.start();countDownLatch.await();System.out.println("  -----------------  main 结束 ----------------- ");}
}

可以看到运行结束,通知事件

自定义计数器

当然我们也可以实现自己的计数器


/*** 自定义 CountDown 计数器*/
public class CountDown {//计数器private int count = 0;private final int total;public CountDown(int total) {this.total = total;}public void countDown() {synchronized (this) {this.count++;//锁住 ++ 通知其他线程this.notifyAll();}}public void aWait() throws InterruptedException {synchronized (this) {while (total != count) {//不等于 则 继续等待this.wait();}}}
}

测试

CountDown countDown = new CountDown( 5);System.out.println(" 准备多线程处理任务 ");IntStream.rangeClosed(1, 5).forEach(x -> {new Thread(() -> {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(" 线程开始 -----  " + Thread.currentThread().getName());countDown.countDown();}, x + "").start();});try {countDown.aWait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(" 准备多线程处理任务 结束 ");System.out.println(" ---------------------- ");System.out.println(" 结束 mian ---------- ");}

测试结果

最后

CountDownLatch 可以用来计数,可以测试任务是否执行结束
也可以用来停止一个线程,也可以用来线程运行结束完后通知事件,彼此工作的线程互相独立不关心。

CountDownLatch用法详解相关推荐

  1. Future 用法详解

    Future 用法详解 前言 其他知识点 Java 多线程基础 深入理解aqs ReentrantLock用法详解 深入理解信号量Semaphore 深入理解并发三大特性 并发编程之深入理解CAS 深 ...

  2. python argv 详解_Python3 sys.argv[ ]用法详解

    sys.argv[]说白了就是一个从程序外部获取参数的桥梁,这个"外部"很关键,因为我们从外部取得的参数可以是多个,所以获得的是一个列表(list),也就是说sys.argv其实可 ...

  3. oracle中的exists 和 not exists 用法详解

    from:http://blog.sina.com.cn/s/blog_601d1ce30100cyrb.html oracle中的exists 和 not exists 用法详解 (2009-05- ...

  4. ROW_NUMBER() OVER()函数用法详解 (分组排序 例子多)

    ROW_NUMBER() OVER()函数用法详解 (分组排序 例子多) https://blog.csdn.net/qq_25221835/article/details/82762416 post ...

  5. python的继承用法_【后端开发】python中继承有什么用法?python继承的用法详解

    本篇文章给大家带来的内容是关于python中继承有什么用法?python继承的用法详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 面向对象三大特征 1.封装:根据职责将属性和方法 ...

  6. C++中substr()函数用法详解

    C++中substr()函数用法详解 原型: string substr (size_t pos = 0, size_t len = npos) const; 返回一个新构造的string对象,其值初 ...

  7. php theme_path,PHP_Yii2主题(Theme)用法详解,本文实例讲述了Yii2主题(Theme) - phpStudy

    Yii2主题(Theme)用法详解 本文实例讲述了Yii2主题(Theme)用法.分享给大家供大家参考,具体如下: 首先看看主要的配置方式: 'components' => [ 'view' = ...

  8. LayoutInflater的inflate函数用法详解

    LayoutInflater的inflate函数用法详解 LayoutInflater作用是将layout的xml布局文件实例化为View类对象. 获取LayoutInflater的方法有如下三种: ...

  9. Ext.Net学习笔记22:Ext.Net Tree 用法详解

    上面的图片是一个简单的树,使用Ext.Net来创建这样的树结构非常简单,代码如下: <ext:TreePanel runat="server"><Root> ...

最新文章

  1. oracle开发常用,oracle开发常用关键字
  2. C基础(31——35)
  3. 牛客网——华为机试(题15:求int型正整数在内存中存储时1的个数)(Java)
  4. SwipeRefreshlayout+RecyclerView+binding实现上拉和下拉刷新
  5. ExtClassLoader和AppClassLoader是Launcher类的两个内部类
  6. [算法][二分查找][排除法]
  7. 白领必看的十种职场致命毒药
  8. 利用open***建立桥接***[zt]
  9. __str__是什么函数_PHP str_shuffle()函数与示例
  10. 2019学python还是php_2019学python还是php
  11. K8s集群部署(四)------ Flannel网络部署
  12. Matlab Tricks(九)—— 矩阵行/列的增广(删除)
  13. mysql insert duplicate key update
  14. POJ - 1384 Piggy-Bank(完全背包)
  15. android 本地阅读pdf,Android 打开本地pdf文件
  16. mysql查询地理位置_利用curl和ip138的数据库来查询IP地址地理位置
  17. 浙江省计算机英语等级考试,2020年上半年浙江省高校计算机等级考试报名(浙江外国语...
  18. window安装Linux
  19. 无盘服务器chkdsk *: /f)修复命令,巧用CHKDSK命令修复U盘文件或目录损坏问题
  20. uni-app开发小程序app页面中获取globalData

热门文章

  1. 在线教育平台开发的影响和意义
  2. Sensors传感器介绍(一)
  3. 嵌入式Linux驱动开发5---并发控制
  4. Uusi 的 Kickstarter 成功秘诀
  5. 基于FastDfs的分布式文件存储系统设计
  6. simsimi 教程 java_用java实现Simsimi小黄鸡接口
  7. 技术演讲,如何快速做到80分(值得收藏)!!!
  8. XNA中 SpriteSortMode 与 BlendState 《摘自王磊文章》
  9. 快递单号查询,物流查询,教你筛选快递代收件
  10. 智慧新零售收银系统小程序商城