概述
CyclicBarrier (周期障碍)类可以帮助同步,它允许一组线程等待整个线程组到达公共屏障点后所有被阻塞的线程才能继续执行。CyclicBarrier好比一扇门,默认情况下关闭状态,堵住了线程执行的道路,直到所有线程都就位,门才打开,让所有线程一起通过。
CyclicBarrier类位于java.util.concurrent包下,CyclicBarrier提供2个构造器:
public CyclicBarrier(int parties, Runnable barrierAction) ;
public CyclicBarrier(int parties);
参数parties指让多少个线程或者任务等待至barrier状态;参数barrierAction为当这些线程都达到barrier状态时会执行的内容。
然后CyclicBarrier中最重要的方法就是await方法,它有2个重载版本:
public int await() throws InterruptedException, BrokenBarrierException)
public int await(long timeout, TimeUnit unit)
第二个版本是让这些线程等待至一定的时间,如果还有线程没有到达barrier状态就直接让到达barrier的线程执行后续任务。
代码示例
1.举一个短跑的例子,每个选手只有在跑道被完全占用的情况下才能起跑,假设10个选手参加比赛,每次跑道只能容纳5个人。
import java.util.concurrent.*;
public class CyclicBarrierTest {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 10; ++i) {
Thread.sleep(2000);
executor.submit(new Runner("" + i));
}
executor.shutdownNow();
}
}
class Runner implements Runnable {
private static CyclicBarrier barrier = new CyclicBarrier(5);
private String name;
public Runner(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("选手 " + name + " is ready");
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("选手 " + name + " 起跑");
}
}
运行结果:
选手 0 is ready
选手 1 is ready
选手 2 is ready
选手 3 is ready
选手 4 is ready
选手 4 起跑
选手 0 起跑
选手 3 起跑
选手 2 起跑
选手 1 起跑
选手 5 is ready
选手 6 is ready
选手 7 is ready
选手 8 is ready
选手 9 is ready
选手 9 起跑
选手 7 起跑
选手 6 起跑
选手 5 起跑
选手 8 起跑
2.考虑另一种场景,假设每个短跑运动员准备起跑的时间最多为1秒,则可以使用带超时时间的await版本。
在上面代码await处加上超时时间
barrier.await(1000,TimeUnit.MILLISECONDS);
运行结果:
选手 0 is ready
选手 0 起跑
选手 1 is ready
选手 1 起跑
选手 2 起跑
选手 3 is ready
选手 3 起跑
选手 4 is ready
选手 4 起跑
选手 5 is ready
选手 5 起跑
选手 6 起跑
选手 7 is ready
选手 7 起跑
选手 8 is ready
选手 8 起跑
选手 9 is ready
选手 9 起跑