概述
CyclicBarrier 的字面意思是'可循环使用的屏障'。它的核心作用是让一组线程在到达某个同步点(屏障)时相互阻塞,直到最后一个线程也到达该点后,屏障才会打开,所有被拦截的线程才能继续运行。
与 CountDownLatch 不同,CyclicBarrier 是可重用的。一旦屏障打开,它可以被重置并再次使用,非常适合需要多次同步的场景。
常用构造方法
CyclicBarrier 提供了两个常用的构造方式:
-
基础构造:
new CyclicBarrier(int parties)参数parties表示屏障拦截的线程数量。每个线程调用await()方法告知已到达屏障,随后当前线程进入阻塞状态。 -
带回调构造:
new CyclicBarrier(int parties, Runnable barrierAction)当所有线程都到达屏障时,会优先执行barrierAction指定的任务。这方便我们在同步点处理一些复杂的业务逻辑,比如数据汇总。
实战示例
下面我们通过一个具体的例子来演示其用法。在这个场景中,我们启动 4 个子线程进行独立计算,它们全部完成后将结果提交给主线程进行汇总拼接,然后再释放线程去执行其他任务。
package com.example.concurrent;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;
/**
* 演示 CyclicBarrier 用法
* 共 4 个子线程,全部完成工作后交出结果,
* 再被统一释放去做自己的事情,而交出的结果被另外的线程拿来拼接字符串
*/
public class UseCyclicBarrier {
// 存放子线程工作结果的容器
private static ConcurrentHashMap<String, Long> resultMap = new ConcurrentHashMap<>();
// 初始化屏障,拦截 4 个线程,并在所有线程到达时执行 CollectThread 的逻辑
private static CyclicBarrier barrier = new CyclicBarrier(4, new CollectThread());
public static void main(String[] args) {
for ( ; i < ; i++) {
( ());
thread.start();
}
}
{
{
();
(Map.Entry<String, Long> workResult : resultMap.entrySet()) {
result.append().append(workResult.getValue()).append();
}
System.out.println( + result);
System.out.println();
}
}
{
{
Thread.currentThread().getId();
resultMap.put(Thread.currentThread().getId() + , id);
{
Thread.sleep( + id);
System.out.println( + id + );
barrier.await();
Thread.sleep( + id);
System.out.println( + id + );
barrier.await();
} (Exception e) {
e.printStackTrace();
}
}
}
}


