CyclicBarrier类

栅栏类似于闭锁,它能阻塞一组线程,直到某个事件发生。栅栏与闭锁的关键区别在于,所有线程必须都到达栅栏的位置时,才能继续执行。

  • 闭锁用于等待事件,栅栏用于等待其他线程。

  • 闭锁是一次性对象,一旦进入终止状态,就不能被重置。栅栏可以使一定数量的参与方反复地在栅栏位置汇集。如果所有线程都到达了栅栏位置,那么栅栏将打开,此时所有线程都被释放,而栅栏将被重置以便下次使用。

闭锁的适用情况

一个老板,有3个员工,每天3个员工都会进行一天的工作,等3个员工都做完了之后,老板才会开始检查每个人的工作。

代码实现

员工代码

public class Worker implements Runnable {
    private String name;
    private CountDownLatch countDownLatch;

    public Worker(String name, CountDownLatch countDownLatch) {
        this.name = name;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        System.out.println("我是" + name + ",我要开始工作了");

        try {
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("我是" + name + ",我的工作干完了");
        //将闭锁的数字减1
        countDownLatch.countDown();
    }
}

老板代码

public class Boss implements Runnable {
    private CountDownLatch countDownLatch;

    public Boss(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        System.out.println("我是老板,我等你们3个人都干完,我再检查");

        try {
            //这行代码会阻塞,直到闭锁的数字置为0
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("我是老板,检查完了");

    }
}

运行

public static void main(String[] args) {
    CountDownLatch countDownLatch = new CountDownLatch(3);

    Worker worker1 = new Worker("wangyingjie",countDownLatch);
    Worker worker2 = new Worker("xiaohei",countDownLatch);
    Worker worker3 = new Worker("xiaopeng",countDownLatch);

    Boss boss = new Boss(countDownLatch);

    new Thread(worker1).start();
    new Thread(worker2).start();
    new Thread(worker3).start();
    new Thread(boss).start();
}

结果

image

栅栏的适用情况

还是这3个员工,这次他们合作做一件事,使用木桩和木板搭桥,每个人打一个木桩,等每个人都打完了,然后3个人一起把木板搭到木桩上。

员工代码

public class Worker implements Runnable {
    private CyclicBarrier cyclicBarrier;
    private String name;

    public Worker(String name, CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println("我是" + name + ",我开始打木桩了");
        System.out.println("我是" + name + ",我打完木桩了,要等待其他人了");
        try {
            //这里开始等待其他人
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }

        System.out.println("我是" + name + ",我们都打完木桩了,一起搭木板吧");
    }
}

运行代码

    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        Worker worker1 = new Worker("xiaohei",cyclicBarrier);
        Worker worker2 = new Worker("laowang",cyclicBarrier);
        Worker worker3 = new Worker("xiaopeng",cyclicBarrier);

        new Thread(worker1).start();
        new Thread(worker2).start();
        new Thread(worker3).start();

    }

运行结果

image