CyclicBarrier(回环栅栏)

CyclicBarrier(回环栅栏)

通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier 可以被重用。我们暂且把这个状态就叫做barrier,当调用 await()方法之后,线程就处于 barrier 了。

await()方法的重载

  • public int await():用来挂起当前线程,直至所有线程都到达 barrier 状态再同时执行后续任务;
  • public int await(long timeout, TimeUnit unit):让这些线程等待至一定的时间,如果还有线程没有到达 barrier 状态就直接让到达 barrier 的线程执行后续任务。

示例代码

public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(2);

        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+"running");
                barrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"finish");
        },"A").start();

        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+"running");
                barrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"finish");
        },"B").start();
    }

部分源码分析

部分成员变量

private static class Generation {
        boolean broken = false;
    }

/** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();
/** The number of parties */
private final int parties;
/* The command to run when tripped */
private final Runnable barrierCommand;
/** The current generation */
private Generation generation = new Generation();

CyclicBarrier是通过ReentrantLock+Condition实现的工具类,里面维护这一个计算器parties来记录个数,当每个线程被barrier.await()时,线程就会被阻塞并且parties会-1操作,当parties变为0时,CyclicBarrier就会唤醒所有线程。

构造函数

public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        this.parties = parties;
        this.count = parties;
        this.barrierCommand = barrierAction;
    }
public CyclicBarrier(int parties) {
        this(parties, null);
    }
posted @ 2021-07-04 20:16  鸭梨的药丸哥  阅读(13)  评论(0)    收藏  举报  来源