CyclicBarrier的使用

允许任意数量的线程 await 等待,直到所有合作线程都达到某个点,然后所有线程从该点继续执行

构造函数

java 复制代码
public CyclicBarrier(int parties) {
    this(parties, null);
}

public CyclicBarrier(int parties, Runnable barrierAction) {
    if (parties <= 0) throw new IllegalArgumentException();
    this.parties = parties;
    this.count = parties;
    this.barrierCommand = barrierAction;
}
  • parties 并行等待的线程个数
  • barrierAction 所有线程都执行等待后,需要运行的代码

方法

java 复制代码
// 当前线程一直等待到 parties 个线程都调用了 await 方法
public int await() throws InterruptedException, BrokenBarrierException {
    try {
        return dowait(false, 0L);
    } catch (TimeoutException toe) {
        throw new Error(toe); // cannot happen
    }
}
// 当前线程等待到 parties 个线程都调用了 await 方法 或者超过 timeout 时间
public int await(long timeout, TimeUnit unit)
    throws InterruptedException,
           BrokenBarrierException,
           TimeoutException {
    return dowait(true, unit.toNanos(timeout));
}

// 线程等待是否被破坏了,比如超时,或者线程 interrupted
public boolean isBroken() {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        return generation.broken;
    } finally {
        lock.unlock();
    }
}
// 重置,CyclicBarrier 可以重复利用,不用重新生成对象
public void reset() {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        breakBarrier();   // break the current generation
        nextGeneration(); // start a new generation
    } finally {
        lock.unlock();
    }
}
// 获取还剩多少个线程没有执行到等待 await
public int getNumberWaiting() {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        return parties - count;
    } finally {
        lock.unlock();
    }
}

使用示例

java 复制代码
public class Main {
    public static final int PARTIES = 3;
    public static final int LEN = 5;
    private Integer[][] mData;
    CyclicBarrier mCyclicBarrier;

    public static void main(String[] args) {
        Main main = new Main();
        main.done();
    }

    private void done() {
        Random random = new Random();
        // 创建 CyclicBarrier 3个线程等待,执行等待后执行的 runnable
        mCyclicBarrier = new CyclicBarrier(PARTIES, () -> {
            // 分别打印 3 个 int 类型数组
            for (int i = 0; i < PARTIES; i++) {
                for (int j = 0; j < LEN; j++) {
                    System.out.print(mData[i][j] + " ");
                }
                System.out.println();
            }
        });
        // 二维数组,3个线程处理一个 5个 数字大小的排序
        mData = new Integer[PARTIES][LEN];

        for (int i = 0; i < PARTIES; i++) {
            mData[i] = new Integer[LEN];
            for (int j = 0; j < LEN; j++) {
                // 构建数据
                mData[i][j] = 100 * i + random.nextInt(50);
            }
            // 启动 3个 线程
            new Thread(new Worker(mData[i], mCyclicBarrier)).start();
        }
    }

    private static class Worker implements Runnable {


        Integer[] mData;
        CyclicBarrier mCyclicBarrier;

        public Worker(Integer[] data, CyclicBarrier cyclicBarrier) {
            mData = data;
            mCyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            Arrays.sort(mData); // 进行排序
            System.out.println(Thread.currentThread().getName() + " : finish...");
            try {
                mCyclicBarrier.await();
                System.out.println(Thread.currentThread().getName() + " await over ...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

输出

erlang 复制代码
Thread-0 : finish...
Thread-2 : finish...
Thread-1 : finish...
0 20 27 41 43 
102 124 126 136 148 
210 233 234 240 246 
Thread-1 await over ...
Thread-0 await over ...
Thread-2 await over ...

说明

  • 同步辅助工具,它允许一组线程全部互相等待以到达一个公共的障碍点。 CyclicBarriers在涉及固定大小的线程方的程序中很有用,该线程方有时必须互相等待。 该屏障称为循环屏障,因为它可以在释放等待线程之后重新使用。
  • CyclicBarrier支持可选的Runnable命令,该命令在障碍中的最后一个线程到达之后但在释放任何线程之前,每个障碍点运行一次。 此屏障操作对于在任何一方继续之前更新共享状态很有用
  • CyclicBarrier 对失败的同步尝试使用全无损坏模型:如果线程由于中断,失败或超时而过早离开障碍点,则所有其他在该障碍点等待的线程也会通过BrokenBarrierException(或InterruptedException)异常离开 他们也大约同时被打断了。
  • 内存一致性影响:调用await()之前的线程中的操作发生在 CyclicBarrier 操作的一部分之前,而其他操作又发生在其他线程中的相应await()成功返回之后的操作之前。
相关推荐
毕业设计7034 分钟前
(免费领源码)SSM董家湾线上点餐系统04682- java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
java·redis·mysql·tomcat·maven·mybatis·ssm
Q264336502325 分钟前
【有源码】基于SpringBoot+Vue的居民健康体检与慢病干预管理系统-面向智慧医疗的体检预约与健康知识服务平台
java·vue.js·spring boot·mysql·毕业设计·javaweb·课程设计
悠仁さん1 小时前
非类型模板参数的特化与偏特化
java·数据结构·算法
鬼手点金1 小时前
上下文:Agent 的眼睛
java·前端·人工智能·git·深度学习
171320330计算机毕设编程1 小时前
计算机毕业设计 基于Hadoop的新能源汽车发展前景分析 LW PPT
java·大数据·hadoop·python·算法·随机森林·线性回归
技术小结-李爽1 小时前
【工具】怎么在终端中启动springboot项目?
java·spring boot·后端·maven
Shaoshing1 小时前
消息发送
java·开发语言
Code_Solitude2 小时前
c语言:指针(3)+冒泡排序
java·c语言·算法
乌暮2 小时前
从 `println` 到生产级日志:Spring Boot 日志体系完全指南
java·开发语言·jvm·spring boot·后端·学习·面试