导读:本期聚焦于小伙伴创作的《Java中的CyclicBarrier怎么用?循环栅栏同步多线程到达屏障点的应用场景有哪些》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Java中的CyclicBarrier怎么用?循环栅栏同步多线程到达屏障点的应用场景有哪些》有用,将其分享出去将是对创作者最好的鼓励。

Java中的CyclicBarrier是java.util.concurrent包下提供的同步辅助类,它的作用是让一组线程互相等待,直到所有线程都到达某个公共屏障点之后,才会继续执行后续的逻辑。和CountDownLatch不同,CyclicBarrier是可以重复使用的,所以也被称为循环栅栏。

Java中的CyclicBarrier怎么用?循环栅栏同步多线程到达屏障点的应用场景有哪些

CyclicBarrier的核心构造方法

CyclicBarrier主要有两个常用的构造方法,开发者可以根据需求选择使用:

  • CyclicBarrier(int parties):创建一个循环栅栏,参数parties表示需要等待的线程数量,当到达的线程数量达到这个值的时候,所有等待的线程就会被唤醒继续执行。
  • CyclicBarrier(int parties, Runnable barrierAction):在上面的构造方法基础上,增加一个屏障动作,当所有线程都到达屏障点之后,会先执行这个barrierAction的逻辑,再唤醒所有等待的线程。

CyclicBarrier的常用API

除了构造方法之外,CyclicBarrier还有几个常用的方法:

  • await():线程调用这个方法之后会进入等待状态,直到所有线程都调用了await方法。
  • await(long timeout, TimeUnit unit):带超时的等待方法,如果超过指定的时间还没有所有线程到达,就会抛出TimeoutException。
  • getParties():获取需要等待的线程总数。
  • getNumberWaiting():获取当前已经到达屏障点的线程数量。
  • reset():重置循环栅栏,会让所有正在等待的线程抛出BrokenBarrierException。

CyclicBarrier基础使用示例

下面通过一个简单的示例演示CyclicBarrier的基本使用,我们创建3个线程,每个线程执行完自己的任务之后调用await方法等待,直到3个线程都到达之后,再一起执行后续逻辑。

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        // 创建循环栅栏,需要等待3个线程,所有线程到达后先打印"所有线程已到达屏障点"
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {
            System.out.println("所有线程已到达屏障点,准备继续执行");
        });

        // 创建3个线程
        for (int i = 0; i < 3; i++) {
            int threadId = i;
            new Thread(() -> {
                try {
                    System.out.println("线程" + threadId + "开始执行任务");
                    // 模拟线程执行任务的耗时
                    Thread.sleep((threadId + 1) * 1000);
                    System.out.println("线程" + threadId + "任务执行完成,到达屏障点等待");
                    // 调用await方法等待其他线程
                    cyclicBarrier.await();
                    System.out.println("线程" + threadId + "继续执行后续逻辑");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

运行上面的代码,输出结果如下,可以看到三个线程各自执行完任务之后都会等待,直到三个都到达之后才一起执行后续逻辑:

线程0开始执行任务
线程1开始执行任务
线程2开始执行任务
线程0任务执行完成,到达屏障点等待
线程1任务执行完成,到达屏障点等待
线程2任务执行完成,到达屏障点等待
所有线程已到达屏障点,准备继续执行
线程2继续执行后续逻辑
线程0继续执行后续逻辑
线程1继续执行后续逻辑

CyclicBarrier的循环使用特性

CyclicBarrier之所以被称为循环栅栏,是因为它在使用完一次之后可以自动重置,不需要手动重新创建就可以再次使用。下面的示例演示它的循环特性,我们让一组线程重复两次到达屏障点:

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierReuseDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> {
            System.out.println("本轮所有线程已到达屏障点,开始下一轮");
        });

        for (int i = 0; i < 2; i++) {
            int round = i;
            new Thread(() -> {
                try {
                    for (int j = 0; j < 2; j++) {
                        System.out.println("线程" + round + "开始第" + j + "轮任务");
                        Thread.sleep(1000);
                        System.out.println("线程" + round + "第" + j + "轮任务完成,到达屏障点");
                        cyclicBarrier.await();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

运行之后可以看到,两次循环中所有线程都会先互相等待,到达屏障点之后再继续执行下一轮,不需要重新创建CyclicBarrier实例。

CyclicBarrier的典型应用场景

1. 分治任务处理

当把一个大任务拆分成多个子任务分给不同线程处理的时候,需要等到所有子任务都处理完成之后,再汇总结果做后续处理,这种场景就非常适合使用CyclicBarrier。比如我们需要计算一个大数组中所有元素的和,可以把数组拆分成几个部分,每个线程计算一部分的和,所有线程计算完成之后,再汇总各个部分的结果得到最终的和。

import java.util.concurrent.CyclicBarrier;

public class SumCalculateDemo {
    private static final int PART_COUNT = 4;
    private static int[] result = new int[PART_COUNT];

    public static void main(String[] args) {
        int[] data = new int[100];
        // 初始化数组,赋值1到100
        for (int i = 0; i < 100; i++) {
            data[i] = i + 1;
        }

        CyclicBarrier cyclicBarrier = new CyclicBarrier(PART_COUNT, () -> {
            // 所有子任务计算完成,汇总结果
            int total = 0;
            for (int num : result) {
                total += num;
            }
            System.out.println("数组所有元素的总和为:" + total);
        });

        // 拆分任务,每个线程计算一部分
        int partSize = data.length / PART_COUNT;
        for (int i = 0; i < PART_COUNT; i++) {
            int start = i * partSize;
            int end = (i == PART_COUNT - 1) ? data.length : start + partSize;
            int partIndex = i;
            new Thread(() -> {
                try {
                    int sum = 0;
                    for (int j = start; j < end; j++) {
                        sum += data[j];
                    }
                    result[partIndex] = sum;
                    System.out.println("子任务" + partIndex + "计算完成,部分和为:" + sum);
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

2. 多阶段计算任务

有些计算任务需要分多个阶段执行,每个阶段都需要所有线程都完成当前阶段的任务,才能进入下一个阶段,这种场景也可以使用CyclicBarrier。比如一个数据处理任务,第一阶段是数据清洗,第二阶段是数据转换,第三阶段是数据入库,每个阶段都需要所有线程完成当前阶段的工作再统一进入下一阶段。

3. 模拟并发测试

在做接口并发测试的时候,需要让多个线程在同一时刻同时发起请求,就可以使用CyclicBarrier。让所有线程准备好之后都调用await方法等待,直到所有线程都准备好,再同时释放,这样就可以模拟出同一时刻的并发请求。

使用CyclicBarrier的注意事项

  • 如果参与等待的线程数量少于构造方法里设置的parties值,那么所有调用await的线程都会一直等待,除非调用了reset方法或者有线程被中断。
  • 如果等待过程中有线程被中断、超时或者调用了reset方法,其他正在等待的线程会抛出BrokenBarrierException,此时CyclicBarrier会被损坏,需要重置之后才能继续使用。
  • 如果构造方法里设置了barrierAction,那么这个动作是由最后一个到达屏障点的线程执行的,要注意这个动作里不要有耗时的操作,否则会影响所有线程的唤醒时间。

CyclicBarrier和CountDownLatch的区别:CountDownLatch是倒计时器,一个线程等待多个线程完成之后再执行,或者多个线程等待一个线程的信号,不能重复使用;而CyclicBarrier是一组线程互相等待,所有线程到达之后一起执行,并且可以循环重复使用。

CyclicBarrier多线程同步循环栅栏线程屏障修改时间:2026-06-14 06:00:46

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。