CyclicBarrier

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();
        }
    }
}

参考资料:

http://cmsblogs.com/?p=2241

原文地址:https://www.cnblogs.com/fruitknife/p/9703134.html