CyclicBarrier
CyclicBarrier,一个同步辅助类,在API中是这么介绍的:
它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
其内部实现使用了ReentrantLock和Condition
/** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();
构造函数
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
重要方法
//当所有的参与者都到达了这个屏障就进行释放,否则一直等待。
其内部使用的是dowait(false, 0L)方法实现
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
//进行超时控制
public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {
return dowait(true, unit.toNanos(timeout));
}
//将屏障重置为初始状态
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // break the current generation
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
}
//返回此时在屏障前等待的线程数
public int getNumberWaiting() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return parties - count;
} finally {
lock.unlock();
}
}
使用案例
场景:四个人相约玩游戏,只有大家都准备的时候,游戏才开始
/**
* @ClassName: PlayThread
* @author: Yang.X.P
* @date: 2018-09-17 15:27
**/
public class PlayThread implements Runnable {
private CyclicBarrier cyclicBarrier = new CyclicBarrier(4, () ->
System.out.println("玩家准备完成,进入游戏中···"));
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "已准备");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
class Game {
public static void main(String[] args) {
PlayThread playThread = new PlayThread();
for(int i = 0; i < 4; i++){
Thread newPlayer = new Thread(playThread);
newPlayer.start();
}
}
}
参考资料: