java.util.concurrent.CyclicBarrier与CountDownLatch非常类似,也可以实现线程间的计数等待,但其功能更为复杂强大;
Barrier意为栅栏,障碍物,阻止线程继续执行,要求在栅栏外等待;
Cyclic意为循环,这个计数器可以循环使用;
示例:司令要求10个士兵一起去完成一项任务;首先要求10个士兵集合报到,然后一起去执行任务,等10个士兵把各自任务都执行完了,司令才能宣布任务完成!
public class CyclicBarrierDemo {
public static class Soldier implements Runnable {
private String name;
private CyclicBarrier cyclic;
public Soldier(CyclicBarrier cyclic, String name) {
this.cyclic = cyclic;
this.name = name;
}
@Override
public void run() {
try {
// 等待所有士兵到齐
cyclic.await();
doWork();
// 等待所有士兵完成工作
cyclic.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
private void doWork() {
try {
TimeUnit.SECONDS.sleep(Math.abs(new Random().nextInt(9)));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + "'s work is done.");
}
}
public static class BarrierRun implements Runnable {
private boolean flag;
int n;
public BarrierRun(boolean flag, int n) {
this.flag = flag;
this.n = n;
}
@Override
public void run() {
if (flag) {
System.out.println("The commander: There are " + n + " soldiers complete the task.");
} else {
System.out.println("The commander: There are " + n + " soldiers get together.");
flag = true;
}
}
}
public static void main(String[] args) {
final int n = 10;
Thread[] allSoldiers = new Thread[n];
boolean flag = false;
CyclicBarrier cyclic = new CyclicBarrier(n, new BarrierRun(flag, n));
System.out.println("Get together now!");
for (int i = 0; i < n; i++) {
String soldierName = "soldier" + i;
System.out.println(soldierName + " arrivals.");
allSoldiers[i] = new Thread(new Soldier(cyclic, soldierName));
allSoldiers[i].start();
//if(i == 5) {
// allSoldiers[i].interrupt();
//}
}
}
}
每一个士兵线程都会执行Soldier类中的run()方法;第一个cyclic.await()方法,每一个士兵线程都会等待,直到10个士兵集合完毕,才会继续向下执行;
集合完毕意味着CyclicBarrier的一次计数完成,当再一次调用await()方法时,会进行下一次计数,即等10个士兵线程都完成各自任务后集合,司令宣布任务完成;
每一次计数完成后都会调用BarrierRun类中的run()方法;
把main方法中注释掉的代码恢复,会得到1个java.lang.InterruptedException和9个java.util.concurrent.BrokenBarrierException;其中InterruptedException是被中断线程抛出的,而BrokenBarrierException则是在等待当前CyclicBarrier上的线程抛出的,可以避免9个线程进行永久的、无谓的等待;