一分钟系列: 闭锁与栅栏

闭锁与栅栏

在介绍闭锁和栅栏之前,我们先来看下这个实例:

我们用三个线程实现男女朋友去看电影的示例,正常情况是需要男女双方都到达后才能一起去看电影,我们看下这段代码:

public class DownLatch {

    private static CountDownLatch countDownLatch = new CountDownLatch(2);
    public static void main(String[] args) throws  InterruptedException {
        new Thread(() -> {
                downLatch.girlArriveMovie();
            }).start();
        new  Thread(()-> {
                downLatch.boyArriveMovie();
        }).start();    
        downLatch.startWatchMovie();
    }
    public  void girlArriveMovie(){
        System.out.println("女孩到达电影院");
    }
    public void boyArriveMovie(){
        System.out.println("男生到达电影院");
    }
    public void startWatchMovie(){
        System.out.println("男女生都到达电影院,开始看电影");
    }
}

可能结果之一:

女孩到达电影院
男女生都到达电影院,开始看电影
男生到达电影院

可能结果之二:

女孩到达电影院
男生到达电影院
男女生都到达电影院,开始看电影

这和我们理想的情况不一样,来看看如何使用闭锁以及栅栏达到我们想要的理想结果。

闭锁

闭锁是一种同步工具。类似于一扇门:在使用闭锁的所有线程到达结束状态之前,这扇门一直是关闭着的。不允许任何线程通过,当到达结束状态时这扇门就会打开并允许所有闭锁相关的线程通过,且当打开了,就永远保持打开状态。
作用:可以用来确保某些任务等到其他任务完成之后才开始执行。

   public class DownLatch {

    private static CountDownLatch countDownLatch = new CountDownLatch(2);

    public static void main(String[] args) throws  InterruptedException {

        DownLatch downLatch = new DownLatch();

        new Thread(() -> {
                downLatch.girlArriveMovie();
                countDownLatch.countDown();
            }).start();
        new  Thread(()-> {
                downLatch.boyArriveMovie();
                countDownLatch.countDown();
        }).start();
        countDownLatch.await();
        downLatch.startWatchMovie();
    }

    public  void girlArriveMovie(){
        System.out.println("女孩到达电影院");
    }

    public void boyArriveMovie(){
        System.out.println("男生到达电影院");
    }

    public void startWatchMovie(){
        System.out.println("男女生都到达电影院,开始看电影");
    }

} 

女孩到达电影院
男生到达电影院
男女生都到达电影院,开始看电影

来看下如何使用闭锁达到我们想要的效果的。

new CountDownLatch(2);
//设置计数器为2
 countDownLatch.countDown();
 // 计数器减一
countDownLatch.await();
//是否计数器未0,如果是等待其他线程执行完毕
//后在执行main线程里的downLatch.startWatchMovie();
//方法

栅栏

栅栏和闭锁可以达到相同的效果,但是不同的是栅栏是等待所有的栅栏工作线程中都到达某一步,所有的栅栏工作线程才会继续执行。


public class CyclicBarrierExample {


    public final static CyclicBarrier cyclicBarrier = new CyclicBarrier(2);


    public static void main(String[] args) {

        CyclicBarrierExample cyclicBarrierExample = new CyclicBarrierExample();
        ExecutorService threadPool = Executors.newFixedThreadPool(2);

        threadPool.execute(() -> cyclicBarrierExample.girlArriveMovie());
        threadPool.execute(() -> cyclicBarrierExample.boyArriveMovie());

        threadPool.shutdown();
    }


    public  void girlArriveMovie(){
        System.out.println("女孩到达电影院");
        try {
            Thread.sleep(500);
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        startWatchMovie();

    }

    public void boyArriveMovie(){
        System.out.println("男生到达电影院");
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        startWatchMovie();
    }

    public void startWatchMovie(){
        System.out.println("男女生都到达电影院,开始看电影");
    }
}

输出结果:

女孩到达电影院
男生到达电影院
男女生都到达电影院,开始看电影
男女生都到达电影院,开始看电影
Thread.sleep(500);
// 执行到这里睡眠500ms
 cyclicBarrier.await();
 //等待其他的栅栏工作线程
 //执行到这里
 //才会继续往下执行
发布了121 篇原创文章 · 获赞 56 · 访问量 167万+

猜你喜欢

转载自blog.csdn.net/u013565163/article/details/87310700