述
CyclicBarrier
循环栅栏同样是一个线程协作工具,和 CountDownLatch
很像,都能阻塞一组线程
作用
当有大量线程相互配合,分别计算不同任务,并且需要最后统一汇总的时候,我们可以使用 CyclicBarrier
,CyclicBarrier
可以构造一个集结点,当某一个线程执行了await()
,它就会到集结点等待,直到所有线程都到了集结点,那么该栅栏就被撤销,所有线程再统一出发,继续执行剩下的任务.
常用方法
- 构造函数,有两个参数,第一个是等待线程的数量,第二个是一个
Runnable
的实现 await()
: 调用的线程进入阻塞状态等待
代码示例
@Slf4j
public class CyclicBarrierDemo {public static void main(String[] args) {CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> log.info("所有线程都到了..."));for (int i = 0; i < 5; i++) {new Thread(new Task(i + 1, cyclicBarrier)).start();}}@AllArgsConstructor@Slf4jstatic class Task implements Runnable{private int id;private CyclicBarrier cyclicBarrier;@Overridepublic void run() {log.info("当前线程正在执行,id:[{}]", id);try {Thread.sleep((long) (Math.random() * 10000));cyclicBarrier.await();log.info("所有线程都到了,继续执行,当前线程id:{}",id);} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}}}}
控制台输出如下:
10:40:34.645 [Thread-1] INFO com.learning.java.cooperation.CyclicBarrierDemo$Task - 当前线程正在执行,id:[2]
10:40:34.645 [Thread-0] INFO com.learning.java.cooperation.CyclicBarrierDemo$Task - 当前线程正在执行,id:[1]
10:40:34.645 [Thread-2] INFO com.learning.java.cooperation.CyclicBarrierDemo$Task - 当前线程正在执行,id:[3]
10:40:34.645 [Thread-3] INFO com.learning.java.cooperation.CyclicBarrierDemo$Task - 当前线程正在执行,id:[4]
10:40:34.645 [Thread-4] INFO com.learning.java.cooperation.CyclicBarrierDemo$Task - 当前线程正在执行,id:[5]
10:40:43.843 [Thread-4] INFO com.learning.java.cooperation.CyclicBarrierDemo - 所有线程都到了...
10:40:43.843 [Thread-4] INFO com.learning.java.cooperation.CyclicBarrierDemo$Task - 所有线程都到了,继续执行,当前线程id:5
10:40:43.843 [Thread-2] INFO com.learning.java.cooperation.CyclicBarrierDemo$Task - 所有线程都到了,继续执行,当前线程id:3
10:40:43.843 [Thread-0] INFO com.learning.java.cooperation.CyclicBarrierDemo$Task - 所有线程都到了,继续执行,当前线程id:1
10:40:43.843 [Thread-1] INFO com.learning.java.cooperation.CyclicBarrierDemo$Task - 所有线程都到了,继续执行,当前线程id:2
10:40:43.843 [Thread-3] INFO com.learning.java.cooperation.CyclicBarrierDemo$Task - 所有线程都到了,继续执行,当前线程id:4
首先声明一个数量是 5 的 CyclicBarrier
, 然后新建5个线程,之后都调用 await()
方法,等到5个线程都调用 await()
方法之后,就会执行构造中传入的 Runnable
的实现, 然后所有线程唤醒,继续执行
对比 CountDownLatch
- 作用不同:
CyclicBarrier
要等到固定数量的线程都到达了栅栏位置才能继续执行,CountDownLatch
只需要在计数器为0的时候就可以继续执行,也就是说CountDownLatch
用于事件,而CyclicBarrier
是用于线程的 - 可重用性不同:
CountDownLatch
再倒数触发门闩打开之后就不能再重用了,而CyclicBarrier
是可以重复使用的