Java多线程中的CyclicBarrier使用方法详解

 更新时间:2023年12月07日 08:30:45   作者:小柴林  
这篇文章主要介绍了Java多线程中的CyclicBarrier使用方法详解,CyclicBarrier是一种同步辅助工具,它允许一组线程都等待对方到达公共障碍点,在涉及固定大小的线程的程序中,CyclicBarriers非常有用,这些线程间必须相互等待,需要的朋友可以参考下

CyclicBarrier

特点

1、同步辅助类

2、同类相互等待(多线程间)

3、计数是加法操作

缺点

1、无法动态添加parties计数

2、调用一次await()仅占用一个parties计数

简述与示例

一种同步辅助工具,它允许一组线程都等待对方到达公共障碍点。在涉及固定大小的线程的程序中,CyclicBarriers非常有用,这些线程间必须相互等待。

该屏障之所以称为cyclic,是因为它可以在等待的线程被释放之后被重用。

CyclicBarrier支持一个可选的Runnable,该命令在每个障碍点运行一次,在多线程中的最后一个线程到达之后,但在所有线程被释放之前。

这个barrier操作对于在任何一方继续之前更新共享状态非常有用。

示例用法:下面是一个在并行分解设计中使用barrier的示例:

public class Solver {
    final int N;
    final float[][] data;
    final CyclicBarrier barrier;
    volatile boolean over = false;
    public Solver(float[][] matrix) throws InterruptedException {
        data = matrix;
        N = matrix.length;
        //每一轮循环都会执行,并且需要run执行完才会触发下一轮开启.
        Runnable barrierAction =
                new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("Solver.run");
                        over = true;
                    }
                };
        //初始化CyclicBarrier
        barrier = new CyclicBarrier(N, barrierAction);
        List<Thread> threads = new ArrayList<>(N);
        for (int i = 0; i < N; i++) {
            Thread thread = new Thread(new Worker(i));
            threads.add(thread);
            thread.start();
        }
        // wait until done
        for (Thread thread : threads) {
            thread.join();
        }
    }
    //程序入口
    public static void main(String[] args) throws InterruptedException {
        float[][] matrix = {{1.2F}, {2.2F}};
        Solver solver = new Solver(matrix);
    }
    class Worker implements Runnable {
        int myRow;
        Worker(int row) {
            myRow = row;
        }
        @Override
        public void run() {
            while (!done()) {
                processRow(myRow);
                try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException ex) {
                    return;
                }
            }
        }
        private void processRow(int myRow) {
            System.out.println("Worker.processRow:" + myRow);
        }
        private boolean done() {
            return over;
        }
    }
}

在这里,每个工作线程处理矩阵中的一行,然后在barrier处等待,直到所有行都处理完毕。

处理完所有行后,将执行提供的Runnable barrier操作并合并行。

如果合并确定找到了一个解决方案,那么done()将返回true,并且每个worker将终止。

如果barrier操作在执行时不依赖于被挂起的参与者,那么参与者中的任何线程都可以在它被释放时执行该操作。

为了方便实现这一点,每次调用await都会返回barrier处该线程的到达索引。

然后您可以选择哪个线程应该执行barrier操作,例如:

 if (barrier.await() == 0) {
   // log the completion of this iteration
 }

CyclicBarrier使用一个动静极限的破碎模型同步尝试失败:如果一个线程离开障碍点过早中断,失败,或超时,所有其他线程等待障碍点也将离开异常通过BrokenBarrierException(或InterruptedException如果他们也被打断了大约在同一时间)。

内存一致性影响:在线程中调用await()之前的操作发生——在barrier操作之前发生——在其他线程中对应的await()成功返回后的操作之前。

方法介绍

构造方法

CyclicBarrier(int parties, Runnable barrierAction) 
//添加线程在屏障达到时触发!线程会阻塞下一轮开始直到该线程执行完毕。

普通方法

int getParties()  //获取当前设置的屏障数
int await()       //等待直到所有线程执行await达到屏障数
int await(long timeout, TimeUnit unit)  //等待直到所有线程执行await达到屏障数或者超过指定超时时间
boolean isBroken()   //查询当前屏障是否处于broken状态
void reset()         //重置当前屏障数到初始时数量
int getNumberWaiting() //查询当前等待未到达屏障值的线程数

到此这篇关于Java多线程中的CyclicBarrier使用方法详解的文章就介绍到这了,更多相关Java的CyclicBarrier内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MyBatis-Plus自动化填充的踩坑记录及解决

    MyBatis-Plus自动化填充的踩坑记录及解决

    这篇文章主要介绍了MyBatis-Plus自动化填充的踩坑记录及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Spring中的@ConditionalOnProperty注解详解

    Spring中的@ConditionalOnProperty注解详解

    这篇文章主要介绍了Spring中的@ConditionalOnProperty注解详解,常见的@Conditionalxxx开头的注解我们称之为条件注解,常见的条件注解有,简单来讲,一般是在配置类上或者是@Bean修饰的方法上,添加此注解表示一个类是否要被Spring上下文加载,需要的朋友可以参考下
    2024-01-01
  • Java后端配置允许跨域方式

    Java后端配置允许跨域方式

    本文介绍了在不同技术和框架中配置跨域资源共享(CORS)的方法,包括使用SpringMVC的@CrossOrigin注解、SpringBoot的全局CORS配置、SpringSecurity中的CORS集成以及手动设置响应头,根据具体需求和技术栈,选择合适的方法来确保跨域请求的安全性和有效性
    2025-02-02
  • 通过一个map替换字符串中指定的字符变量方法

    通过一个map替换字符串中指定的字符变量方法

    下面小编就为大家带来一篇通过一个map替换字符串中指定的字符变量方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • MyBatis中#{} 和 ${} 的区别和动态 SQL详解

    MyBatis中#{} 和 ${} 的区别和动态 SQL详解

    这篇文章主要介绍了MyBatis中#{}和${}的区别,包括参数传递、安全性、性能等方面,然后详细介绍了如何使用#{}和${}进行排序、模糊查询、动态SQL、数据库连接池等操作,最后,总结了注解方式的动态SQL,感兴趣的朋友跟随小编一起看看吧
    2024-11-11
  • 浅谈java二进制、十进制、十六进制、字符串之间的相互转换

    浅谈java二进制、十进制、十六进制、字符串之间的相互转换

    下面小编就为大家带来一篇浅谈二进制、十进制、十六进制、字符串之间的相互转换。小编觉得挺不错的,现在就分享给大家,也给大家做个参考,一起跟随小编过来看看吧
    2016-06-06
  • IntelliJ IDEA远程Debug Linux的Java程序,找问题不要只会看日志了(推荐)

    IntelliJ IDEA远程Debug Linux的Java程序,找问题不要只会看日志了(推荐)

    这篇文章主要介绍了IntelliJ IDEA远程Debug Linux的Java程序,找问题不要只会看日志了,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • 详解Spring Boot使用系统参数表提升系统的灵活性

    详解Spring Boot使用系统参数表提升系统的灵活性

    Spring Boot项目中常有一些相对稳定的参数设置项,其作用范围是系统级的或模块级的,这些参数称为系统参数。这些变量以参数形式进行配置,从而提高变动和扩展的灵活性,保持代码的稳定性
    2021-06-06
  • Spring Boot面试题总结

    Spring Boot面试题总结

    这篇文章主要介绍了Spring Boot面试题总结,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-09-09
  • Java设计模式之23种设计模式详解

    Java设计模式之23种设计模式详解

    这篇文章主要介绍了Java设计模式之23种设计模式详解,设计模式使代码编制真正工程化,设计模式是软件工程的基石,项目中合理的运用设计模式可以完美的解决很多问题,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07

最新评论