我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java中CyclicBarrier 循环屏障

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java中CyclicBarrier 循环屏障

一、简介

CyclicBarrier 字面意思回环栅栏(循环屏障),它可以实现让一组线程等待至某个状态(屏障点)之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。 

CyclicBarrier 作用是让一组线程相互等待,当达到一个共同点时,所有之前等待的线程再继续执行,且 CyclicBarrier 功能可重复使用。

二、CyclicBarrier的使用

构造方法:

 // parties表示屏障拦截的线程数量,每个线程调用 await 方法告诉 CyclicBarrier 我已经到达了屏障,然后当前线程被阻塞。
 public CyclicBarrier(int parties)
 // 用于在线程到达屏障时,优先执行 barrierAction,方便处理更复杂的业务场景(该线程的执行时机是在到达屏障之后再执行)

重要方法:

//屏障 指定数量的线程全部调用await()方法时,这些线程不再阻塞
// BrokenBarrierException 表示栅栏已经被破坏,破坏的原因可能是其中一个线程 await() 时被中断或者超时
public int await() throws InterruptedException, BrokenBarrierException
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
//循环  通过reset()方法可以进行重置

CyclicBarrier 应用场景

  • 利用 CyclicBarrier 可以用于多线程计算数据,最后合并计算结果的场景。
  • 利用 CyclicBarrier的计数器能够重置,屏障可以重复使用的特性,可以支持类似“人满发车”的场景

模拟合并计算场景

利用 CyclicBarrier 可以用于多线程计算数据,最后合并计算结果的场景。

public class CyclicBarrierTest2 {
    //保存每个学生的平均成绩
    private Conc urrentHashMap<String, Integer> map=new ConcurrentHashMap<String,Integer>();
    private ExecutorService threadPool= Executors.newFixedThreadPool(3);
    private CyclicBarrier cb=new CyclicBarrier(3,()->{
        int result=0;
        Set<String> set = map.keySet();
        for(String s:set){
            result+=map.get(s);
        }
        System.out.println("三人平均成绩为:"+(result/3)+"分");
    });
    public void count(){
        for(int i=0;i<3;i++){
            threadPool.execute(new Runnable(){

                @Override
                public void run() {
                    //获取学生平均成绩
                    int score=(int)(Math.random()*40+60);
                    map.put(Thread.currentThread().getName(), score);
                    System.out.println(Thread.currentThread().getName()
                            +"同学的平均成绩为:"+score);
                    try {
                        //执行完运行await(),等待所有学生平均成绩都计算完毕
                        cb.await();
                    } catch (InterruptedException | BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }

            });
        }
    }
    public static void main(String[] args) {
        CyclicBarrierTest2 cb=new CyclicBarrierTest2();
        cb.count();
    }
}

模拟“人满发车”的场景

利用CyclicBarrier的计数器能够重置,屏障可以重复使用的特性,可以支持类似“人满发车”的场景

public class CyclicBarrierTest3 {
    public static void main(String[] args) {
        AtomicInteger counter = new AtomicInteger();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                5, 5, 1000, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(100),
                (r) -> new Thread(r, counter.addAndGet(1) + " 号 "),
                new ThreadPoolExecutor.AbortPolicy());

        CyclicBarrier cyclicBarrier = new CyclicBarrier(5,
                () -> System.out.println("裁判:比赛开始~~"));

        for (int i = 0; i < 10; i++) {
            threadPoolExecutor.submit(new Runner(cyclicBarrier));
        }

    }
    static class Runner extends Thread{
        private CyclicBarrier cyclicBarrier;
        public Runner (CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }
        @Override
        public void run() {
            try {
                int sleepMills = ThreadLocalRandom.current().nextInt(1000);
                Thread.sleep(sleepMills);
                System.out.println(Thread.currentThread().getName() + " 选手已就位, 准备共用时: " + sleepMills + "ms" + cyclicBarrier.getNumberWaiting());
                cyclicBarrier.await();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }catch(BrokenBarrierException e){
                e.printStackTrace();
            }
        }
    }

}

输出结果:

3 号  选手已就位, 准备共用时: 78ms0
1 号  选手已就位, 准备共用时: 395ms1
5 号  选手已就位, 准备共用时: 733ms2
2 号  选手已就位, 准备共用时: 776ms3
4 号  选手已就位, 准备共用时: 807ms4
裁判:比赛开始~~
4 号  选手已就位, 准备共用时: 131ms0
3 号  选手已就位, 准备共用时: 256ms1
2 号  选手已就位, 准备共用时: 291ms2
1 号  选手已就位, 准备共用时: 588ms3
5 号  选手已就位, 准备共用时: 763ms4
裁判:比赛开始~~

三、CyclicBarrier 源码分析

CyclicBarrier 流程

主要是的流程:

  • 获取锁 如果 count != 0 就进入阻塞;
  • 进入阻塞之前,首先需要进入条件队列,然后释放锁,最后阻塞;
  • 如果 count != 0 会进行一个唤醒,将所有的条件队列中的节点转换为阻塞队列;
  • 被唤醒过后会进行锁的获取,如果锁获取失败,会进入 lock 的阻塞队列;
  • 如果锁获取成功,进行锁的释放,以及唤醒,同步队列中的线程。

下面是一个简单的流程图:

下面是具体的一些代码调用的流程:

几个常见的问题?

  • 1.一组线程在触发屏障之前互相等待,最后一个线程到达屏障后唤醒逻辑是如何实现的. 唤醒的过程是通过调用 java.util.concurrent.locks.Condition#signalAll唤醒条件队列上的所有节点。
  • 2.删栏循环使用是如何实现的? 实际上一个互斥锁 ReentrantLock 的条件队列和阻塞队列的转换。
  • 3.条件队列到同步队列的转换实现逻辑 ? 转换过程中,首先会先将条件队列中所有的阻塞线程唤醒,然后会去获取 lock 如果获取失败,就进入同步队列。

CyclicBarrier 与 CountDownLatch的区别

  • CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset() 方法重置。所以CyclicBarrier能处理更为复杂的业务场景,比如如果计算发生错误,可以重置计数器,并让线程们重新执行一次
  • CyclicBarrier还提供getNumberWaiting(可以获得CyclicBarrier阻塞的线程数量)、isBroken(用来知道阻塞的线程是否被中断)等方法。
  • CountDownLatch会阻塞主线程,CyclicBarrier不会阻塞主线程,只会阻塞子线程。
  • CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同。CountDownLatch一般用于一个或多个线程,等待其他线程执行完任务后,再执行。CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行。
  • CyclicBarrier 还可以提供一个 barrierAction,合并多线程计算结果。
  • CyclicBarrier是通过ReentrantLock的"独占锁"和Conditon来实现一组线程的阻塞唤醒的,而CountDownLatch则是通过AQS的“共享锁”实现

到此这篇关于Java中CyclicBarrier 循环屏障的文章就介绍到这了,更多相关Java CyclicBarrier 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java中CyclicBarrier 循环屏障

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java中CyclicBarrier循环屏障怎么应用

这篇“Java中CyclicBarrier循环屏障怎么应用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java中Cycli
2023-06-30

JavaCountDownLatch计数器与CyclicBarrier循环屏障

CountDownLatch是一种同步辅助,允许一个或多个线程等待其他线程中正在执行的操作的ASET完成。它允许一组线程同时等待到达一个共同的障碍点
2023-05-14

Java CountDownLatch计数器与CyclicBarrier循环屏障怎么定义

本文小编为大家详细介绍“Java CountDownLatch计数器与CyclicBarrier循环屏障怎么定义”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java CountDownLatch计数器与CyclicBarrier循环屏障
2023-07-05

JUC循环屏障CyclicBarrier与CountDownLatch区别详解

这篇文章主要为大家介绍了JUC循环屏障CyclicBarrier与CountDownLatch区别详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-08

AQS同步组件CyclicBarrier循环屏障用例剖析

这篇文章主要为大家介绍了AQS同步组件CyclicBarrier循环屏障用例剖析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

Java循环屏障中CyclicBarrier如何实现多线程分段等待执行完成

Java循环屏障中CyclicBarrier如何实现多线程分段等待执行完成,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。前言工作中是否有这样的场景,多个线程任务
2023-06-25

Java并发编程回环屏障CyclicBarrier实例分析

本文小编为大家详细介绍“Java并发编程回环屏障CyclicBarrier实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java并发编程回环屏障CyclicBarrier实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入
2023-06-30

java中map如何循环取key

小编给大家分享一下java中map如何循环取key,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!import java.awt.List;import java.util.ArrayList;import java.uti
2023-06-03

java中如何结束if循环

在实际编程中,有时需要在条件语句匹配的时候跳出循环。在Java里,由break和continue语句控制。“break”语句“break”语句用来结束循环,即不再执行后边的所有循环。示例:计算1+2+3+4......+100的结果。public class
java中如何结束if循环
2017-07-13

Java中如何实现While循环

Java中如何实现While循环,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 一、循环结构语句1.在我们实际生活中经常会把同一件事情重复做好几次。例如:潮汕人喜欢喝茶,只
2023-06-16

Java和Python中for循环的比较

Java是强类型的语言,而python是弱类型的语言。先看Java中的for循环使用,如下图:package test06;public cl
2023-01-31

Java中如何实现do while循环

小编给大家分享一下Java中如何实现do while循环,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!import java.util.Scanner;public clas
2023-06-02

详解Java中的增强 for 循环 foreach

foreach 是 Java 中的一种语法糖,几乎每一种语言都有一些这样的语法糖来方便程序员进行开发,编译期间以特定的字节码或特定的方式来对这些语法进行处理。能够提高性能,并减少代码出错的几率。在 Java 中还有比如 泛型、自动拆箱、自动
2023-05-31

java中for循环的方式有哪些

Java中for循环的方式有以下几种:1. 基本for循环:在已知循环次数的情况下使用,适用于遍历数组或集合等固定大小的数据结构。```javafor (int i = 0; i // 循环体}```2. 增强for循环:用于遍历数组或集合
2023-10-07

java中for循环的作用是什么

在 Java 中,for 循环用于重复执行特定的代码块,其作用包括:迭代数组或集合:通过 for 循环可以遍历数组、集合或其他可迭代对象中的元素。执行固定次数的循环操作:通过指定循环的初始条件、循环条件和迭代步骤,可以实现按照一定规则重复
java中for循环的作用是什么
2024-03-13

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录