CyclicBarrier

49 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第19天,点击查看活动详情

  • 栅栏类似于闭锁(CountDownLatch),它能阻塞一组线程直到某个事件的发生。栅栏与闭锁的关键区别在于, 所有的线程必须同时到达栅栏位置,才能继续执行。闭锁用于等待事件,而 栅栏用于等待其他线程
  • CyclicBarrier可以使一定数量的线程反复地在栅栏位置处汇集。 当线程到达栅栏位置时将调用await方法,这个方法将阻塞直到所有线程都到达栅栏位置。  如果所有线程都到达栅栏位置,那么栅栏将打开,此时所有的线程都将被释放,而栅栏将被重置以便下次使用。
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,() -> System.out.println("全部完成"));

        for (int i = 0; i < 7; i++) {
             final int temp = i + 1;
             new Thread(() ->{
                System.out.println(Thread.currentThread().getName() + "\t第" + temp + "次");
                 try {
                     int await = cyclicBarrier.await();
                     System.out.println("还剩:" + await);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 } catch (BrokenBarrierException e) {
                     e.printStackTrace();
                 }
             },"线程" + String.valueOf(i)).start();
        }
    }

CyclicBarrier 与 CountDownLatch 区别

  • CountDownLatch 是一次性的。 CyclicBarrier 是可循环利用的
  • CountDownLatch 参与的线程的职责是不一样的,有的在倒计时,有的在等待倒计时结束。 CyclicBarrier 参与的线程职责是一样的

javadoc是这么描述它们的:

  • CountDownLatch: A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
  • CyclicBarrier : A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
  • 从javadoc的描述可以得出: CountDownLatch:一个或者多个线程,等待其他多个线程完成某件事情之后才能执行; CyclicBarrier:多个线程互相等待,直到到达同一个同步点,再继续一起执行。
  • 对于CountDownLatch来说,重点是“一个线程(多个线程)等待”,而其他的N个线程在完成“某件事情”之后,可以终止,也可以等待。 而对于CyclicBarrier,重点是多个线程,在任意一个线程没有完成,所有的线程都必须互相等待,然后继续一起执行。 CountDownLatch是计数器,线程完成一个记录一个,只不过计数不是递增而是递减,而CyclicBarrier更像是一个阀门,需要所有线程都到达,阀门才能打开,然后继续执行。 按照这个题目的描述等所有线程都到达了这一个阀门处,再一起执行,此题强调的是,一起继续执行,我认为 选B 比较合理!
  • 像上文中CountDownLatch的例子,main线程在等待,其余6个线程任务做完之后,main线程才苏醒干后面的事。因为countdown只会阻塞调用者,其它线程干完任务就可以干其他事。这里的调用者线程就是main线程。
  • 像上文中CyclicBarrier的例子,是7个线程互相等待对方,7个任务都完成后,执行注册的回调任务。