Java同步工具类——栅栏[CyclicBarrier]

本文的概念来自《Java并发编程实战》

我们前面已经介绍了通过闭锁来启动一组相关的操作,或者等待一组相关的操作结束。闭锁是一次性对象,一旦进入终止状态就不能被重置。

栅栏(Barrier)类似于闭锁,它能阻塞一组线程直到某个事件发生。栅栏与闭锁的关键区别在于,所有的线程必须同时到达栅栏位置,才能继续执行。闭锁用于等待事件,而栅栏用户等待其他线程。栅栏用于实现一些协议,例如几个家庭决定在某个地方集合:“所有人6:00在麦当劳碰头,到了以后要等其他人,之后在讨论下一步要做的事情。”

CyclicBarrier可以使一定数量的参与方反复的在栅栏位置汇集,它在并行迭代算法中非常常用:这种算法通常将一个问题拆分成为一系列相互独立的自问题。当线程到达栅栏位置时将调用await()方法,这个方法将阻塞直到所有的线程到达栅栏位置。如果所有的线程都到达栅栏位置,那么栅栏将打开,此时所有的线程都被释放,而栅栏将被重置一遍下次使用。如果对await()方法的调用超时,或者await阻塞的线程被中断,那么栅栏就认为是被打破了,所有阻塞的await都将终止并且抛出BorkenBarrierException。如果成功的通过栅栏,那么await将会为每个线程都返回一个唯一的索引号,我们 可以利用这些索引来”选举”产生一个“领导线程”,并在下一次迭代中由该领导线程执行一些特殊的工作。

CyclicBarrier是功能强大的工具类,不过下面我们通过一个简单的例子来感受一下它的部分功能

上个星期我和朋友去吃自助,然后服务员说你们人太少了,要等其他人一起拼桌orz…,下面我们就把我和朋友当作线程,把服务员当作栅栏来应用一下CyclicBarrier]

public class CellularTest {
    private final CyclicBarrier cyclicBarrier;

    public CellularTest(int count) {
        cyclicBarrier = new CyclicBarrier(count, new Runnable() {
            @Override
            public void run() {
                System.out.println("有三个人到了,将他们带到餐桌");
            }
        });
    }

    public CyclicBarrier getCyclicBarrier() {
        return cyclicBarrier;
    }

    public static void main(String[] args) {
        CellularTest cellularTest = new CellularTest(3);
        for(int i = 0; i < 9; ++i) {
            Thread thread = new Thread() {
                @Override
                public void run() {
                    try {
                        System.out.println(this.getName() + " 等待服务员发话");
                        cellularTest.getCyclicBarrier().await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            };
            thread.start();
        }
    }
}
/**
Thread-0 等待服务员发话
Thread-1 等待服务员发话
Thread-2 等待服务员发话
有三个人到了,将他们带到餐桌
Thread-3 等待服务员发话
Thread-4 等待服务员发话
Thread-5 等待服务员发话
有三个人到了,将他们带到餐桌
Thread-6 等待服务员发话
Thread-7 等待服务员发话
Thread-8 等待服务员发话
有三个人到了,将他们带到餐桌
*/

你可能感兴趣的:(Java并发)