简介
上次简要介绍了 CountDownLatch ,CountDownLatch只能使用一次,想要循环使用我们就需要用CyclicBarrier。
方法类似
- 构造参数 N 仍为倒计时起始数据 count
- 多出来一个可选的 Runnable 参数 为count=0时要执行的任务
- await(); 当前线程挂起,直到 count=0;此时会执行 Runnable 任务,然后唤醒所有挂起的线程继续执行,并将count重新置为N,开启一个新的纪元
示例程序:
- 赛马比赛终点35m
- 3匹马每秒前进1次
- 3匹马每次能随机前进 0-5m
- 3匹马都前进一次后进行检查谁到达的终点
- 如果有到达终点的就结束比赛,否则继续前进
代码
赛马
public class HorseRace {
static final int FINISH_LINE = 35;
private List<Horse> horses = new ArrayList<>();
private ExecutorService exec = Executors.newCachedThreadPool();
private CyclicBarrier barrier;
public HorseRace(int nHorse, final int pause) {
/**
* count 为0 时,执行runnable,然后唤醒所有 parties
*/
barrier = new CyclicBarrier(nHorse, () -> {
StringBuilder s = new StringBuilder();
for (int i = 0; i < FINISH_LINE; i++) {
s.append("=");
}
System.out.println(s);
horses.forEach(horse -> System.out.println(horse.tracks()));
for (Horse horse : horses) {
if (horse.getStrides() >= FINISH_LINE) {
System.out.println(horse + " won!");
exec.shutdownNow();
return;
}
}
try {
TimeUnit.MILLISECONDS.sleep(pause);
} catch (InterruptedException e) {
System.out.println("barrier-action sleep interrupted");
}
});
for (int i = 0; i < nHorse; i++) {
Horse horse = new Horse(barrier);
horses.add(horse);
exec.execute(horse);
}
}
public static void main(String[] args) {
int nHorses = 3;
int pause = 1000;
new HorseRace(nHorses, pause);
}
}
public class Horse implements Runnable {
private static int counter = 0;
private final int id = counter++;
private int strides = 0;
private static Random random = new Random(47);
private CyclicBarrier barrier;
public Horse(CyclicBarrier barrier) {
this.barrier = barrier;
}
public synchronized int getStrides() {
return strides;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
strides += random.nextInt(5);
}
// 使当前线程处于等待状态,当barrier中所有线程的任务都完成(处于等待状态时)又开始执行
barrier.await();
}
} catch (InterruptedException e) {
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return "Horse " + id + " ";
}
public String tracks() {
StringBuilder s = new StringBuilder();
for (int i = 0; i < getStrides(); i++) {
s.append("*");
}
s.append(id);
return s.toString();
}
}
结果
===================================
***0
1
***2
===================================
****0
****1
****2
===================================
******0
*******1
****2
===================================
********0
**********1
*******2
===================================
************0
**************1
********2
===================================
*************0
*****************1
***********2
===================================
*************0
********************1
************2
===================================
**************0
**********************1
************2
===================================
*****************0
**************************1
*************2
===================================
*******************0
**************************1
*************2
===================================
***********************0
**************************1
*****************2
===================================
*************************0
***************************1
******************2
===================================
*****************************0
******************************1
**********************2
===================================
********************************0
*******************************1
**********************2
===================================
*********************************0
**********************************1
************************2
===================================
*************************************0
**********************************1
**************************2
Horse 0 won!