Java并发编程--JUC并发工具类之CyclicBarrier

摘要

  • 本文介绍CyclicBarrier相关技术

  • 本文基于jdk1.8

CyclicBarrier介绍

  • CyclicBarrier(回环栅栏或循环屏障),是 Java 并发库中的一个同步工具,通过它可以实现让一组线程等待至某个状态(屏障点)之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。

  • CyclicBarrier内部维护了一个计数器,当线程到达临界点时,会调用await()方法进行等待。当计数器达到指定的数量时,所有等待的线程都会被释放,并继续执行后续操作。

CyclicBarrier的常用方法

方法 描述
CyclicBarrier(int parties) 构造函数, parties表示屏障拦截的线程数量,每个线程调用 await 方法告诉 CyclicBarrier 我已经到达了屏
障,然后当前线程被阻塞。
CyclicBarrier(int parties, Runnable barrierAction) 构造函数,用于在线程到达屏障时,优先执行 barrierAction,方便处理更复杂的业务场景(该线程的执行时机是
在到达屏障之后再执行)
await()方法 线程通过调用await()方法进入等待状态,直到所有线程到达临界点。计数器将重置,并且所有等待的线程会被释放继续执行。
await(long timeout, TimeUnit unit)方法 超时等待
getParties()方法 获取参与线程的数量。
reset()方法 重置计数器,可以复用CyclicBarrier对象。
isBroken()方法 判断等待的线程是否被中断。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
public static void main(String[] args) {
final int THREAD_COUNT = 3;
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT, new Runnable() {
@Override
public void run() {
System.out.println("All threads have reached the barrier. Let's continue!");
}
});

// 创建并启动三个线程
for (int i = 1; i <= THREAD_COUNT; i++) {
Thread thread = new Thread(new Worker(barrier, "Thread " + i));
thread.start();
}
}

static class Worker implements Runnable {
private final CyclicBarrier barrier;
private final String name;

public Worker(CyclicBarrier barrier, String name) {
this.barrier = barrier;
this.name = name;
}

@Override
public void run() {
System.out.println(name + " has started its task.");

// 模拟工作
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(name + " has reached the barrier.");
try {
barrier.await(); // 等待其他线程到达栅栏
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}

System.out.println(name + " has continued its task.");
}
}
}
  • 在上述示例中,我们创建了一个CyclicBarrier对象,并指定参与线程的数量为3

  • 每个线程在执行任务前会先打印一条信息,然后模拟工作2秒钟。

  • 接着,线程会调用barrier.await()方法等待其他线程到达栅栏。

  • 当所有线程都到达栅栏后,其中一个线程会执行栅栏构造函数中传入的Runnable对象,并打印一条提示信息。

  • 之后,所有线程会继续执行各自的任务。

CyclicBarrier的应用场景

  • 多线程任务:CyclicBarrier 可以用于将复杂的任务分配给多个线程执行,并在所有线程完成工作后触发后续操作。

  • 数据处理:CyclicBarrier 可以用于协调多个线程间的数据处理,在所有线程处理完数据后触发后续操作。

CyclicBarrier 与 CountDownLatch 区别

  • CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的

  • CountDownLatch 参与的线程的职责是不一样的,有的在倒计时,有的在等待倒计时结束。CyclicBarrier 参与的线程职责是一样的。