01 CyclicBarrier
CyclicBarrier 提供了如下功能:
(1)向上增加计数的功能
(2)阻塞等待功能
(3)阶段性同步功能(线程数大于 parties 数量时)
(4)支持多次循环实现多个线程一起执行的目的。
02 与 CountDownLatch 的比较
(1)CountDownLatch 时计数器做减法,而 CyclicBarrier 时通过累加来实现。
(2)CountDownLatch 只支持单次多个线程阻塞然后一起执行,CyclicBarrier 是支持多次的。
03 常用方法
await()
阻塞等待,直到达到构造函数中指定的数量之后继续向下执行。
getNumberWaiting()
获取有几个线程已到了阻塞节点
isBroken()
查询阻塞是否受到损坏,这里的损坏指的是当出现异常后 阻塞节点是否还能够正常工作。
例如: 5 个线程线程阻塞时有一个线程抛出了 NullPointException,那么只有抛出 NullPointException 的线程停止运行,其他 4 个线程依然在运行。
再比如:5 个线程中有一个线程执行了 interruput() 中断,那么其他几个阻塞等待的线程都会停止运行。阻塞节点被破坏。
getParties()
获取构造函数中指定的 parties 数
reset()
重置阻塞。
04 案例
10 个运动员(Runner)参加淘汰赛,两两一组比赛。
Runner.java
package com.page.concurrent.cyclicbarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class Runner extends Thread {
private final CyclicBarrier cyclicBarrier;
private final int number;
public Runner(CyclicBarrier cyclicBarrier, int number) {
this.cyclicBarrier = cyclicBarrier;
this.number = number;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()
+ ":"
+ System.currentTimeMillis()
+ " Ready. Waiting another one.");
try {
Thread.sleep(1000 * number);
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName() + " run.");
} catch (InterruptedException e) {
System.out.println("had exception when waiting others. e=" + e.getMessage());
} catch (BrokenBarrierException e) {
System.out.println("had exception when waiting others. e" + e.getMessage());
}
}
}
Game.java
package com.page.concurrent.cyclicbarrier;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CyclicBarrier;
public class Game {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(2,
() -> System.out.println(System.currentTimeMillis() + ">>>> 2 runner had ready."));
List<Runner> runners = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
Runner runner = new Runner(cyclicBarrier, i);
runner.start();
runners.add(runner);
}
}
}