一、CountDownLatch

  它被用来同步一个或多个任务,强制他们等待其他任务完成,这就是闭锁。

  1. public CountDownLatch(int count) {
  2. if (count < 0) throw new IllegalArgumentException("count < 0");
  3. this.sync = new Sync(count);
  4. }

  类中只有一个构造函数,一个int类型的参数count,代表计数器。这个计数器的初始值是线程的数量,每当一个线程结束,count-1,当count==0 时,所有线程执行完毕,在闭锁上等待的线程就可以执行了。

类中还包含了三个公共方法:

  1. public void await()
  1. public boolean await(long timeout, TimeUnit unit)
  1. public void countDown()

  当每个任务完成时,都会调用countDown()方法。而等待问题被解决的任务在这个锁存器上调用await()方法,这个任务就相当于被挂起了直到 timeout 或 计数器为0

  1. public class CountDownLatchDemo {
  2. static final int SIZE = 5;
  3.  
  4. public static void main(String[] args) {
  5. ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5));
  6. CountDownLatch countDownLatch = new CountDownLatch(SIZE);
  7. pool.execute(new WaitTask(countDownLatch));
  8. for (int i = 0; i < SIZE; i++) {
  9. pool.execute(new TaskNow(countDownLatch));
  10. }
  11. }
  12.  
  13. }
  14.  
  15. class TaskNow implements Runnable {
  16. private final CountDownLatch countDownLatch;
  17.  
  18. TaskNow(CountDownLatch countDownLatch) {
  19. this.countDownLatch = countDownLatch;
  20. }
  21.  
  22. @Override
  23. public void run() {
  24. try {
  25. TimeUnit.MILLISECONDS.sleep(2000);
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. }
  29. System.out.println("我没完事你别想跑");
  30. //调用countDown()的方法会减少count次数直到为0,调用await的任务才能进行
  31. countDownLatch.countDown();
  32. }
  33. }
  34.  
  35. class WaitTask implements Runnable {
  36. private final CountDownLatch countDownLatch;
  37.  
  38. WaitTask(CountDownLatch countDownLatch) {
  39. this.countDownLatch = countDownLatch;
  40. }
  41.  
  42. @Override
  43. public void run() {
  44. try {
  45. //调用await的任务会被挂起
  46. countDownLatch.await();
  47. System.out.println("终于轮到我了");
  48. } catch (InterruptedException e) {
  49. e.printStackTrace();
  50. }
  51. }
  52. }
    结果:

  我没完事你别想跑
  我没完事你别想跑
  我没完事你别想跑
  我没完事你别想跑
  我没完事你别想跑
  终于轮到我了

二、CylicBarrier

  栅栏类似于闭锁,只是要等到所有线程都到达栅栏,才能进行接下来的动作,在没到达栅栏之前先到的要等待。

构造方法

共有两个构造方法:

  1. public CyclicBarrier(int parties, Runnable barrierAction) {
  2. if (parties <= 0) throw new IllegalArgumentException();
  3. this.parties = parties;
  4. this.count = parties;
  5. this.barrierCommand = barrierAction;
  6. }
  7. public CyclicBarrier(int parties) {
  8. this(parties, null);
  9. }

CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程使用await()方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。

CyclicBarrier的另一个构造函数CyclicBarrier(int parties, Runnable barrierAction),用于线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景。

await()方法

  线程调用await()方法表示已经到达同步点,然后当前线程被阻塞。直到parties个参与线程调用了await()方法,CyclicBarrier同样提供带超时时间的await和不带超时时间的await方法:

  1. public int await() throws InterruptedException, BrokenBarrierException {
  2. try {
  3. return dowait(false, 0L);
  4. } catch (TimeoutException toe) {
  5. throw new Error(toe); // cannot happen
  6. }
  7. }
  8. public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException{...}

  可以看到await方法调用了dowait()方法,dowait()方法是核心方法其内容是:如果这个线程不是最后一个到达的线程那么进行等待直到:

  • 最后一个线程到达,即index == 0
  • 某个参与线程等待超时
  • 某个参与线程被中断
  • 调用了CyclicBarrier的reset()方法。该方法会将屏障重置为初始状态

案例

  1. public class CycliBarrierDemo {
  2.  
  3. public static void main(String[] args) {
  4. int threadCount = 3;
  5. CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount);
  6. ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1));
  7. for (int i = 0; i < threadCount; i++) {
  8. pool.execute(new Horse(cyclicBarrier, i));
  9. }
  10. }
  11. }
  12.  
  13. class Horse implements Runnable {
  14. private CyclicBarrier cyclicBarrier;
  15. private int num;
  16.  
  17. public Horse(CyclicBarrier cyclicBarrier, int num) {
  18. this.cyclicBarrier = cyclicBarrier;
  19. this.num = num;
  20. }
  21.  
  22. @Override
  23. public void run() {
  24. System.out.println("马匹:" + num + "到了");
  25. try {
  26. cyclicBarrier.await();
  27. System.out.println("马匹:" + num + "在等待");
  28. TimeUnit.MILLISECONDS.sleep(2000);
  29. } catch (InterruptedException | BrokenBarrierException e) {
  30. e.printStackTrace();
  31. }
  32. System.out.println("马匹到齐");
  33. }
  34. }
  35.  
  36. 结果:

  马匹:0到了
  马匹:2到了
  马匹:1到了
  马匹:1在等待
  马匹:0在等待
  马匹:2在等待
  马匹到齐
  马匹到齐
  马匹到齐

  1.  

  

CountDownLatch和CycliBarrier介绍的更多相关文章

  1. CountDownLatch和CylicBarrier以及Semaphare你使用过吗

    CountDownLatch 是什么 CountDownLatch的字面意思:倒计时 门栓 它的功能是:让一些线程阻塞直到另一些线程完成一系列操作后才唤醒. 它通过调用await方法让线程进入阻塞状态 ...

  2. Java并发之CountDownLatch工具类

    一.CountDownLatch工具类介绍 CountDownLatch类是Java并发工具常用的四大工具之一,CountDownLatch允许一个或者多个线程等待其他线程完成工作.假设我们有这样的一 ...

  3. 对CountDownLatch的初步学习

    CountDownLatch的中文翻译为"闭锁",在JDK1.5中 CountDownLatch类加入进来.为程序猿进行并发编程提供有利的帮助. 首先我们先看看JDK文档中对于Co ...

  4. java高级---->Thread之CountDownLatch的使用

    CountDownLatch是JDK 5+里面闭锁的一个实现,允许一个或者多个线程等待某个事件的发生.今天我们通过一些实例来学习一下它的用法. CountDownLatch的简单使用 CountDow ...

  5. CountDownLatch、CyclicBarrier、Semaphore、Exchanger 的详细解析

    本文主要介绍和对比我们常用的几种并发工具类,主要涉及 CountDownLatch . CyclicBarrier . Semaphore . Exchanger 相关的内容,如果对多线程相关内容不熟 ...

  6. 【Java线程安全】 — 常用数据结构及原理(未完结)

    本文主要记录自己对于多线程安全的学习,先来记几个线程安全模型. 首先最重要的当然是volatile和AQS了: 我们知道,整个java.cuncurrent包的核心就是volatile,CAS加自旋悲 ...

  7. 通过一个生活中的案例场景,揭开并发包底层AQS的神秘面纱

    本文导读 生活中案例场景介绍 联想到 AQS 到底是什么 AQS 的设计初衷 揭秘 AQS 底层实现 最后的总结 当你在学习某一个技能的时候,是否曾有过这样的感觉,就是同一个技能点学完了之后,过了一段 ...

  8. Zookeeper--0300--java操作Zookeeper,临时节点实现分布式锁原理

    删除Zookeeper的java客户端有  : 1,Zookeeper官方提供的原生API, 2,zkClient,在原生api上进行扩展的开源java客户端 3, 一.Zookeeper原生API ...

  9. java 利用同步工具类控制线程

    前言 参考来源:<java并发编程实战> 同步工具类:根据工具类的自身状态来协调线程的控制流.通过同步工具类,来协调线程之间的行为. 可见性:在多线程环境下,当某个属性被其他线程修改后,其 ...

随机推荐

  1. 全文搜索引擎 Elasticsearch

    写在前面 最近在学Elasticsearch , 我相信只要是接触过开发的都会听过Elasticsearch或ELK这么一个技术. 主要用来做全文检索或大数据分析等,之前一直处理了解状态. 所以打算系 ...

  2. python连接数据库查询

    import sqlite3 as db conn = db.connect(r'D:/data/test.db') print ('Opend database successfully \n') ...

  3. Spring 梳理 - @Component

    使用@Component注解,表示该类定义为Spring管理Bean,使用默认value(可选)属性表示Bean标识符.如果不指定标识符,默认为首字母小写类名.例如类UserController的标识 ...

  4. Fork/Join 框架框架使用

    1.介绍 Fork/Join 框架是 Java7 提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架.在多核计算机中正确使用可以很好的 ...

  5. IT架构师技术知识图谱

    互联网上“最全的技术图谱”,记录下.来源:http://developer.51cto.com/art/201708/548757.htm 1 1.1 架构师图谱 1.2 Java架构师图谱 1.3 ...

  6. Hbase入门(四)——表结构设计-RowKey

    Hbase的表结构设计与关系型数据库有很多不同,主要是Hbase有Rowkey和列族.timestamp这几个全新的概念,如何设计表结构就非常的重要. 创建 Hbase就是通过 表 Rowkey 列族 ...

  7. 由std::once_call 引发的单例模式的再次总结,基于C++11

    一个偶然的机会,知道了std::once_call这个东西. 了解了下,std::once_call支持多线程情况下的某函数只执行一次.咦,这个不是恰好符合单例模式的多线程安全的困境吗? 单例模式,经 ...

  8. redis系列之------简单的动态字符串(SDS)

    前言 Redis 没有直接使用 C 语言传统的字符串表示(以空字符结尾的字符数组,以下简称 C 字符串), 而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的 ...

  9. opencv之膨胀与腐蚀

    腐蚀和膨胀 Erosion/Dilation erosion/dilation,用白话说,就是让图像亮的区域收缩和扩张. 原理 我们定义一个卷积核矩阵.这个矩阵可以是任何形状的,但通常而言,是矩形或者 ...

  10. day 23

    目录 面向对象总复习 面向对象总复习 面向过程编程思想: ​ 核心是过程,过程指的是做事情的步骤,即先干什么再干什么. ​ 基于该编程思想编程,就好比一条流水线,一种机械式的思维方式. 面向对象编程思 ...