有时候会有这样的需求,多个线程同时工作,然后其中几个可以随意并发执行,但有一个线程需要等其他线程工作结束后,才能开始。举个例子,开启多个线程分块下载一个大文件,每个线程只下载固定的一截,最后由另外一个线程来拼接所有的分段,那么这时候我们可以考虑使用CountDownLatch来控制并发。

CountDownLatch是JAVA提供在java.util.concurrent包下的一个辅助类,可以把它看成是一个计数器,其内部维护着一个count计数,只不过对这个计数器的操作都是原子操作,同时只能有一个线程去操作这个计数器,CountDownLatch通过构造函数传入一个初始计数值,调用者可以通过调用CounDownLatch对象的cutDown()方法,来使计数减1;如果调用对象上的await()方法,那么调用者就会一直阻塞在这里,直到别人通过cutDown方法,将计数减到0,才可以继续执行。

/*** Created by DELL on 2017/1/4.*/
import java.util.concurrent.CountDownLatch;public class Thread2 {/*** 计数器,用来控制线程* 传入参数2,表示计数器计数为2*/private final static CountDownLatch mCountDownLatch = new CountDownLatch(2);/*** 示例工作线程类*/private static class WorkingThread extends Thread {private final String mThreadName;private final int mSleepTime;public WorkingThread(String name, int sleepTime) {mThreadName = name;mSleepTime = sleepTime;}@Overridepublic void run() {System.out.println("[" + mThreadName + "] started!");try {Thread.sleep(mSleepTime);} catch (InterruptedException e) {e.printStackTrace();}mCountDownLatch.countDown();//减一System.out.println("[" + mThreadName + "] end!");}}/*** 示例线程类*/private static class SampleThread extends Thread {@Overridepublic void run() {System.out.println("[SampleThread] started!");try {// 会阻塞在这里等待 mCountDownLatch 里的count变为0;// 也就是等待另外的WorkingThread调用countDown()mCountDownLatch.await();} catch (InterruptedException e) {}System.out.println("[SampleThread] end!");}}public static void main(String[] args) throws Exception {// 最先run SampleThreadnew SampleThread().start();// 运行两个工作线程// 工作线程1运行5秒new WorkingThread("WorkingThread1", 5000).start();// 工作线程2运行2秒new WorkingThread("WorkingThread2", 2000).start();}
}

执行结果如下:

[SampleThread] started![WorkingThread2] started![WorkingThread1] started![WorkingThread2] end![WorkingThread1] end![SampleThread] end!

CyclicBarrier 例子如下:

import java.util.concurrent.CyclicBarrier;/*** Created by DELL on 2017/1/4.*/
public class thread3 {public static final int INIT_NUM = 5;public static void main(String[] args) {CyclicBarrier cyc = new CyclicBarrier(INIT_NUM, new Runnable() {@Overridepublic void run() {System.out.println("init cyclicBarrier----");}});for (int i = 0; i < INIT_NUM; i++) {new sampleCyclic(cyc).start();}}private static class sampleCyclic extends Thread {CyclicBarrier barrier;public sampleCyclic(CyclicBarrier barrier) {this.barrier = barrier;}@Overridepublic void run() {System.out.println("start=====");try {barrier.await();} catch (Exception e) {e.printStackTrace();}System.out.println("id" + Thread.currentThread().getId() + "working----");}}}

输出结果如下:

start=====
start=====
start=====
start=====
start=====
init cyclicBarrier----
id16working----
id13working----
id15working----
id14working----
id12working----

综上所述二者有甚区别呢?

CountDownLatch CyclicBarrier
减计数方式 加计数方式
计算为0时释放所有等待的线程 计数达到指定值时释放所有等待线程
计数为0时,无法重置 计数达到指定值时,计数置为0重新开始
调用countDown()方法计数减一,调用await()方法只进行阻塞,对计数没任何影响 调用await()方法计数加1,若加1后的值不等于构造方法的值,则线程阻塞
不可重复利用 可重复利用

  

CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。CyclicBarrier : N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。
这样应该就清楚一点了,对于CountDownLatch来说,重点是那个“一个线程”, 是它在等待, 而另外那N的线程在把“某个事情”做完之后可以继续等待,可以终止。而对于CyclicBarrier来说,重点是那N个线程,他们之间任何一个没有完成,所有的线程都必须等待。

CountDownLatch 是计数器, 线程完成一个就记一个, 就像 报数一样, 只不过是递减的.

而CyclicBarrier更像一个水闸, 线程执行就想水流, 在水闸处都会堵住, 等到水满(线程到齐)了, 才开始泄流.

转载于:https://www.cnblogs.com/baizhanshi/p/6247850.html

CountDownLatch和CyclicBarrier 举例详解相关推荐

  1. java web几百万分页_举例详解用Java实现web分页功能的方法

    举例详解用Java实现web分页功能的方法 发布于 2020-11-25| 复制链接 摘记: 分页问题是一个非常普遍的问题,开发者几乎都会遇到,这里不讨论具体如何分页,说明一下Web方式下分页的原理. ...

  2. 数据库事务隔离级别举例详解

    目录 一.前言 1.1.4种事务隔离级别 1.2.3种读现象 二.举例说明 2.1.读未提交 2.2.读已提交 2.3.可重复读 2.4.串行化 一.前言 本文主要对4种事务隔离级别,具体举例说明各自 ...

  3. CyclicBarrier 用法详解

    CyclicBarrier 用法详解 CyclicBarrier使用场景 用于协调多个线程同步执行操作的场合,所有线程等待完成,然后一起做事情( 相互之间都准备好,然后一起做事情 ) 例如百米赛跑,必 ...

  4. java barrier_Java并发类CyclicBarrier方法详解

    Cyclic是周期的意思,Barrier是关卡的意思.CyclicBarrier不仅有CountDownLatch的功能,还可以实现屏障等待,即阶段性同步.因此适用于,需要循环地实现线程一起做任务的目 ...

  5. join和countDownLatch原理及区别详解

    先上结论 原理 join 原理:在当前线程中调用另一个线程线程 thread 的 join() 方法时,会调用该 thread 的 wait() 方法,直到这个 thread 执行完毕(JVM在 ru ...

  6. java基础-泛型举例详解

    泛型 泛型是JDK5.0增加的新特性,泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数.这种类型参数可以在类.接口.和方法的创建中,分别被称为泛型类.泛型接口.泛型方法. 一.认识泛型 在没 ...

  7. 数据结构--队列、双端队列实际举例详解(Python代码)

    https://blog.csdn.net/hanhanwanghaha宝藏女孩 欢迎您的关注! 欢迎关注微信公众号:宝藏女孩的成长日记 让这个可爱的宝藏女孩在努力的道路上与你一起同行! 如有转载,请 ...

  8. java泛型实例化_java基础-泛型举例详解

    泛型 泛型是JDK5.0增加的新特性,泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数.这种类型参数可以在类.接口.和方法的创建中,分别被称为泛型类.泛型接口.泛型方法. 一.认识泛型 在没 ...

  9. ipv6的127位掩码如何表示_计算机子网掩码知识举例详解

    子网掩码是网络工程中一个很重要的知识点,什么是子网掩码呢,很多对网络了解不深的朋友都对子网掩码有些困惑, 不了解它有什么用?其实子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分. ...

  10. CyclicBarrier 使用详解

    前言 CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最一个线程到达屏障时,屏障才会开 ...

最新文章

  1. Google全球员工围攻Google!
  2. WebUI中DataGrid多层表头的终极解决办法
  3. Android--Genymotion虚拟机(模拟器)的配置
  4. javascript创建类方法汇总(包含es6语法)
  5. Android中Spinner的使用
  6. 社交网络图中结点的“重要性“计算(Dijkstra + SPFA + Floyd + 模板)
  7. T-SQL | 你需要了解的执行计划
  8. 【git系列】切换分支相关命令
  9. 商务先锋 多功能一体化网络营销软件
  10. CentOS系统安装Java
  11. selenium chromedriver usage
  12. Word2vec 详解
  13. event mpm php,Apache下三种MPM模式:prefork,worker和event
  14. ADS(Advanced Design system)良率分析(Yield)、良率优化(YieldOptim)
  15. ie9 java小程序设置_小程序 自定义导航栏
  16. 汉堡造型的动态导航菜单,非常有意思
  17. 港科夜闻|2022年香港科大气候适应及复原力大会圆满闭幕,政经领袖研讨香港气候政策与绿色金融发展...
  18. python做三国杀
  19. 用业绩倒逼技术发展,小i机器人朱频频:AI价值不仅在于IPO
  20. mysql用户的创建、修改、删除与密码修改

热门文章

  1. 上传文件数据 Requests
  2. ②⓪②⓪ → ②⓪②①
  3. 每日一题[LeetCode 689]三个无重叠子数组的最大和
  4. 时间序列-N_LSTM
  5. 深度学习2.0-41.GRU原理及实战
  6. bug2-Internal Error: Blas GEMM launch failed 问题
  7. 力扣每日一刷--验证回文串
  8. python基础4-序列
  9. 《流畅的Python第二版》读书笔记
  10. LeetCode刷题——11. 盛最多水的容器