JAVA并发包中有三个类用于同步一批线程的行为,分别是闭锁(Latch),信号灯(Semaphore)和栅栏(CyclicBarrier)。本贴主要说明闭锁(Latch)和栅栏(CyclicBarrier)。

1. 闭锁(Latch)

闭锁(Latch)  —— 确保多个线程在完成各自事务后,才会打开继续执行后面的内容,否则一直等待。

计数器闭锁(CountDownLatch) —— 是JDK5+ 里面闭锁的一个实现,允许一个或多个线程等待某个事件的发生。CountDownLatch  有个正数的计数器,countDown(); 对计数器做减法操作,await(); 等待计数器 = 0。所有await的线程都会阻塞,直到计数器为0或者等待线程中断或者超时。

 public static void main(String[] args) throws InterruptedException {
// 申明,等待事件数量 5次
CountDownLatch await = new CountDownLatch(5); // 依次创建并启动处于等待状态的5个MyRunnable线程
for (int i = 1; i < 6; ++i) {
new Thread(new MyRunnable(await, i)).start();
} System.out.println("等待线程开始工作......");
await.await();
System.out.println("结束!");
}
 public static class MyRunnable implements Runnable {

     private final CountDownLatch await;
private final int num; public MyRunnable(CountDownLatch await, int num) {
this.await = await;
this.num = num;
} public void run() {
try {
System.out.println("线程"+num+"执行完毕。");
await.countDown(); // 当前事件执行完毕,计数 -1
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
等待线程开始工作......
线程1执行完毕。
线程2执行完毕。
线程3执行完毕。
线程4执行完毕。
线程5执行完毕。
结束!

流程如图所示:

图1 - CountDownLatch 处理流程

2. 栅栏(CyclicBarrier)

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

场景: 比如甲乙丙三人一把椅子,甲做椅子腿,乙做椅子面,丙做椅子靠背。等3人都做成后,就可以组装成椅子了。这是一种并行迭代,将一个问题分成很多子问题,当一系列的子问题都解决之后(所有子问题线程都已经await(); ),此时将栅栏打开,所有子问题线程被释放,而栅栏位置可以留着下次使用。

示例如下:

 public static void main(String[] args) throws InterruptedException {
// 申明,等待线程数量 3次
CyclicBarrier cyclicBarrier = new CyclicBarrier(3); // 依次创建并启动处于等待状态的3个MyRunnable2线程
new Thread(new ChairRunnable(cyclicBarrier, "椅子腿")).start();
new Thread(new ChairRunnable(cyclicBarrier, "椅子面")).start();
new Thread(new ChairRunnable(cyclicBarrier, "椅子背")).start();
}
 public static class ChairRunnable implements Runnable {
private final CyclicBarrier cyclicBarrier;
private final String event; public ChairRunnable(CyclicBarrier cyclicBarrier, String event) {
this.cyclicBarrier = cyclicBarrier;
this.event = event;
} public void run() {
try {
System.out.println("开始做【" + event + "】。");
Thread.sleep(new Random().nextInt(10000));
cyclicBarrier.await(); // 等待其他线程完成
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("【" + event + "】做好了, 我们来一起组装吧!");
}
}
运行结果:
开始做【椅子腿】。
开始做【椅子背】。
开始做【椅子面】。
【椅子面】做好了, 我们来一起组装吧!
【椅子腿】做好了, 我们来一起组装吧!
【椅子背】做好了, 我们来一起组装吧!

流程如下图所示:

图2 - CyclicBarrier 处理流程

Java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)的更多相关文章

  1. java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)

    -闭锁(Latch) 闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态.通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都将通过, ...

  2. 并发编程 04——闭锁CountDownLatch 与 栅栏CyclicBarrier

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  3. java 多线程并发系列之 生产者消费者模式的两种实现

    在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...

  4. java高并发系列 - 第16天:JUC中等待多线程完成的工具类CountDownLatch,必备技能

    这是java高并发系列第16篇文章. 本篇内容 介绍CountDownLatch及使用场景 提供几个示例介绍CountDownLatch的使用 手写一个并行处理任务的工具类 假如有这样一个需求,当我们 ...

  5. 从火箭发场景来学习Java多线程并发闭锁对象

    从火箭发场景来学习Java多线程并发闭锁对象 倒计时器场景 在我们开发过程中,有时候会使用到倒计时计数器.最简单的是:int size = 5; 执行后,size—这种方式来实现.但是在多线程并发的情 ...

  6. Java高并发系列——检视阅读

    Java高并发系列--检视阅读 参考 java高并发系列 liaoxuefeng Java教程 CompletableFuture AQS原理没讲,需要找资料补充. JUC中常见的集合原来没讲,比如C ...

  7. Java 多线程并发编程一览笔录

    Java 多线程并发编程一览笔录 知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run ...

  8. Java多线程并发07——锁在Java中的实现

    上一篇文章中,我们已经介绍过了各种锁,让各位对锁有了一定的了解.接下来将为各位介绍锁在Java中的实现.关注我的公众号「Java面典」了解更多 Java 相关知识点. 在 Java 中主要通过使用sy ...

  9. [转]Java多线程干货系列—(一)Java多线程基础

    Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...

随机推荐

  1. ajax前端传递对象给后端

    前端操作如下即可:

  2. jQuery实现回车键抬起触发事件

    $(function(){ //回车键按下触发 $(document).keydown(function(event){ if(event.keyCode==13){ alert("niha ...

  3. js 实现浏览器全屏效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. sql server 表连接类型

    一.数据库访问操作 1.SCAN(最影响性能点,优化切入点) 根据表的不同,分为Table Scan,Cluster Index Scan,Non-clustered Index Scan Table ...

  5. udev规则,部署Multipath

    部署Multipath多路径环境 配置iSCSI服务 编写udev规则 配置并访问NFS共享 部署Multipath多路径环境 1 配置iSCSI服务 1.1 问题 本案例要求先搭建好一台iSCSI服 ...

  6. 以数字资产模型为核心驱动的一站式IoT数据分析实践

    [摘要] 一个不会直播的云服务架构师,不是一个好的攻城狮! 在这个全民直播的时代 一个不会直播的云服务架构师 不是一个好的攻城狮 3月23日15:00-15:50,华为云IoT物联网数据分析服务架构师 ...

  7. Vue-router 第5节 vue-router利用url传递参数

    Vue-router 第5节 vue-router利用url传递参数 目录 Vue-router 第5节 vue-router利用url传递参数 第5节 vue-router利用url传递参数 冒号的 ...

  8. matlab计算相对功率

    1.对脑电数据进行db4四层分解,因为脑电频率是在0-64HZ,分层后如图所示, 细节分量[d1 d2 d3 d4] 近似分量[a4] 重建细节分量和近似分量,然后计算对应频段得相对功率谱,重建出来得 ...

  9. 空间小姐姐生活照,我用python破解加密压缩包,无忧查看

    事情的经过是这样的: 又是奶茶,行吧行吧. 快点开工,争取李大伟回来之前搞定. 李大伟说是6位数字密码 那么我们可以利用python生成全部的六位数字密码 #生成从000000到99999的密码表f ...

  10. 如何将dotnet core webapi发布到docker中…

    如何将dotnet core webapi发布到docker中 今天想起来撸一下docker,中途还是遇到些问题,但是这些问题都是由于路径什么的导致不正确,在这儿还是记录下操作过程,今天是基于wind ...