同步屏障CyclicBarrier

同步屏障CyclicBarrier的作用是让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,所有被屏障阻塞的线程才会继续运行。

默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法后当前线程会被阻塞。

CyclicBarrier的使用

使用两个拦截线程数作为初始化参数,如下代码:

public class CyclicBarrierTest {
    staticCyclicBarrier c = new CyclicBarrier(2);
    public static void main(String[] args) {
    new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            c.await();
        } catch (Exception e) {}
            System.out.println(1);
        }
    }).start();
    try {
        c.await();
    } catch (Exception e) {}
        System.out.println(2);
    }
}

产生两种可能顺序:

1
2

2
1

如果代码不变,把new CyclicBarrier(2)修改成new CyclicBarrier(3),则线程会永远等待,因为没有第三个线程到达屏障,所以之前到达屏障的两个线程都不会继续执行。

CyclicBarrier还提供一个更高级的构造函数CyclicBarrier(int parties, Runnable barrierAction),用于在线程到达屏障时,优先执行barrierAction。如下代码:

import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest2 {
static CyclicBarrier c = new CyclicBarrier(2, new A());
    public static void main(String[] args) {
        new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                c.await();
            } catch (Exception e) {}
            System.out.println(1);
        }
        }).start();
        try {
            c.await();
        } catch (Exception e) {}
        System.out.println(2);
    }
    static class A implements Runnable {
        @Override
        public void run() {
            System.out.println(3);
        }
    }
}
3
1
2

上面代码必须等到代码中的线程A和第一个线程都执行完之后,才会继续执行主线程。

CyclicBarrier和CountDownLatch的区别

CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置。如何业务上要求在线程处理过程中出错,需要重新处理,就只能使用CyclicBarrier。两者的关键区别在于:CountDownLatch(闭锁)用于等待事件,而CyclicBarrier用于等待其他线程。

另外,CyclicBarrier来提供了两个方法,getNumberWaiting()用于获取CyclicBarrier阻塞的线程数量,isBroken()方法用来判断阻塞线程是否被中断。

参考

最后修改日期: 2019年10月7日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。