一、介绍
CyclicBarrier也叫同步屏障,在JDK1.5被引入的一个同步辅助类,在API中是这么介绍的:
允许一组线程全部等待彼此达到共同屏障点的同步辅助。 循环阻塞在涉及固定大小的线程方的程序中很有用,这 些线程必须偶尔等待彼此。 屏障被称为循环,因为它可以在等待的线程被释放之后重新使用。
CyclicBarrier好比一扇门,默认情况下关闭状态,堵住了线程执行的道路,直到所有线程都就位,门才打开,让所有线程一起通过。
二、实现分析
通过上图我们可以看到 CyclicBarrier的内部是使用重入锁ReentrantLock和Condition。它有两个构造方法:
• CyclicBarrier(int parties) :它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动屏障时执行预定义的操作。parties表示拦截线程的数量。
• CyclicBarrier(int parties, Runnable barrierAction) :创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动屏障时执行给定的屏障操作,该操作由最后一个进入屏障的线程执行。
构造方法如下:
public CyclicBarrier(int parties, Runnable barrierAction) { if (parties <= 0) throw new IllegalArgumentException(); this.parties = parties; this.count = parties; this.barrierCommand = barrierAction; } public CyclicBarrier(int parties) { this(parties, null); }
在CyclicBarrier中最重要的方法莫过于await()方法,每个线程调用await方法告诉CyclicBarrier已经到达屏障位置,线程被阻塞。源码如下:
public int await() throws InterruptedException, BrokenBarrierException { try { return dowait(false, 0L); } catch (TimeoutException toe) { throw new Error(toe); // cannot happen } }
await()方法的逻辑:如果该线程不是到达的最后一个线程,则他会一直处于等待状态,除非发生以下情况:
1. 最后一个线程到达,即index == 0
2 . 超出了指定时间(超时等待)
3. 其他的某个线程中断当前线程
4. 其他的某个线程中断另一个等待的线程
5. 其他的某个线程在等待屏障超时
6. 其他的某个线程在此屏障调用reset()方法。reset()方法用于将屏障重置为初始状态。
三、案例
田径比赛,所有运动员准备好了之后,大家一起跑,代码如下
public class Demo1CyclicBarrier { public static void main(String[] args) { // 拦截线程的数量为5 CyclicBarrier cyclicBarrier = new CyclicBarrier(5); List<Thread> threadList = new ArrayList<>(); for (int i = 0; i < 5; i++) { Thread t = new Thread(new Athlete(cyclicBarrier, "运动员" + i)); threadList.add(t); } for (Thread t : threadList) { // 通过遍历逐一启动线程 t.start(); } } static class Athlete implements Runnable { private CyclicBarrier cyclicBarrier; private String name; public Athlete(CyclicBarrier cyclicBarrier, String name) { this.cyclicBarrier = cyclicBarrier; this.name = name; } @Override public void run() { System.out.println(name + "就位"); try { // 每个线程调用await方法告诉CyclicBarrier已经到达屏障位置,线程被阻塞 // 如果该线程不是到达的最后一个线程,则他会一直处于等待状态 cyclicBarrier.await(); System.out.println(name + "跑到终点。"); } catch (Exception e) { } } } }
结果如下:
运动员0就位 运动员1就位 运动员2就位 运动员3就位 运动员4就位 运动员4跑到终点。 运动员3跑到终点。 运动员2跑到终点。 运动员1跑到终点。 运动员0跑到终点。
即运动员全部就位之后才会开始跑步。
标签:cyclicBarrier,屏障,运动员,线程,CyclicBarrier,就位,循环 From: https://www.cnblogs.com/zwh0910/p/17014398.html