首页 > 其他 > 详细

CountDownLatch和CylicBarrier以及Semaphare你使用过吗

时间:2019-07-12 00:00:35      阅读:134      评论:0      收藏:0      [点我收藏+]

CountDownLatch

是什么

CountDownLatch的字面意思:倒计时
它的功能是:让一些线程阻塞直到另一些线程完成一系列操作后才唤醒。
它通过调用await方法让线程进入阻塞状态等待倒计时0时唤醒。
它通过线程调用countDown方法让倒计时中的计数器减去1,当计数器为0时,会唤醒哪些因为调用了await而阻塞的线程。

案例

假设老板开一个紧急会议,他先到会议室等着所有人签到然后开始开会,可以使用CountDownLatch进行模拟。

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

        for (int i=1;i<=5;i++){
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"签到!");
                countDownLatch.countDown();
            },"第"+i+"個人").start();
        }


        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("老板宣布人夠了开始开会!");
    }

运行结果:

//注意这里的签到顺序可以随意
第1個人签到!
第2個人签到!
第3個人签到!
第4個人签到!
第5個人签到!
老板宣布人夠了开始开会!

CyclicBarrier

是什么

CyclicBarrier [?sa?kl?k] [?b?ri?r] 的字面意思:可循环使用的屏障
它的功能是:让一组线程到达一个屏障时被阻塞,知道最后一个线程到达屏障,所有被屏障拦截的线程才会继续执行。
它通过调用await方法让线程进入屏障,

图例

技术分享图片

例子

还是上面的开会的例子,我们使用CyclicBarrier实现。

public static void main(String[] args) {
        CyclicBarrier cyclicBarrier=new CyclicBarrier(5,()->{
            System.out.println("老板宣布人夠了开始开会!!");
        });

        for (int i=1;i<=5;i++){
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName()+"签到!");
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },"第"+i+"個人").start();
        }
    }

运行结果:

第1個人签到!
第2個人签到!
第3個人签到!
第4個人签到!
第5個人签到!
老板宣布人夠了开始开会!!
  • 假设有个需求要随机给100个vip会员发邀请短信,如果发完之后发送一个邮件告诉管理员,也可以使用这个,而且也可以利用重置计数的特性再随机发送100个!

Semaphor

是什么

Semaphor [?sem?f??r] 信号量的意思;
它主要用于两个目的:

  • 用于多个共享资源互斥使用。
    一个停车场有多个停车位,这多个停车位对应汽车来说就是多个共享资源,Semaphor可以实现多个停车位和多个汽车之间的互斥。
  • 用于并发线程数的控制。(就是控制同时得到共享资源的线程数量)
    在创建Semaphor时可以指定并发线程数,
    //permits :允许
    public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }
    //还可以指定是否为公平锁
    public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }
  • 信号量为1时 相当于独占锁 信号量大于1时相当于共享锁。

例子

假设现在是年终,总经理和副总经理要求所有部分要进行述职汇报工作,这两个老总为了提高效率在办公室里决定并行听取工作,使用Semaphor进行模拟。
根据需求我们可以确定共享资源为两个老总,并发汇报工作的最多两个部门。

 public static void main(String[] args) {
        Semaphore semaphore=new Semaphore(2);
        for (int i=1;i<=6;i++){
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName()+"到了办公室门口,等待述职!");
                    semaphore.acquire();
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();
                    System.out.println(Thread.currentThread().getName()+"述职中完毕!");
                }
            },"第"+i+"部门").start();
        }
    }

运行效果:

第1部门到了办公室门口,等待述职!
第2部门到了办公室门口,等待述职!
第3部门到了办公室门口,等待述职!
第4部门到了办公室门口,等待述职!
第6部门到了办公室门口,等待述职!
第5部门到了办公室门口,等待述职!

第1部门述职中完毕!
第2部门述职中完毕!

第3部门述职中完毕!
第4部门述职中完毕!

第6部门述职中完毕!
第5部门述职中完毕!

注意结果:第1部门和第2部门是同时进行述职的,是两两进行的,也就是说我们控制了多线程情况下对共享资源访问时并发线程的数量。

CountDownlatch和CyclicBarrier以及Semaphor的区别是

  • CountDownLatch是做减法,CyclicBarrier是做加法,Semaphor的临界资源可以反复使用

  • CountDownLatch不能重置计数,CycliBarrier提供的reset()方法可以重置计数,不过只能等到第一个计数结束。Semaphor可以重复使用。

  • CountDownLatch和CycliBarrier不能控制并发线程的数量,Semaphor可以实现控制并发线程的数量。

CountDownLatch和CylicBarrier以及Semaphare你使用过吗

原文:https://www.cnblogs.com/wangsen/p/11170709.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!