美文网首页
7、那些基于AQS的同步器

7、那些基于AQS的同步器

作者: 神秘空指针 | 来源:发表于2018-09-29 19:20 被阅读0次

之前说过AQS 是所有同步器的基础,那么我们就来说说那些基于AQS的同步工具吧

1、Semaphore 信号量

Semaphore(信号量)是一个控制并发数量两的同步器(吐槽:这名字和功能有毛线关系啊),他的构造接受一个int 参数,代表着并发数,当并发数,超过这个数就去队列中排队吧(这和读写锁中 读锁不是异曲同工吗,只不过读锁无法设置共享的线程数)。原理很好理解的吧,下面看看用法:

 public static void main(String[] args) {

        Semaphore semaphore = new Semaphore(5);

        for (int i = 0; i < 6; i++) {
            new Thread(() -> {
                try {
                    String name = Thread.currentThread().getName();
                    System.out.println(name + " 我来上厕所了");
                    boolean b = semaphore.tryAcquire();
                    if (!b){
                        System.out.println(name + " 我没抢到坑位了");
                    }
                    System.out.println(name + " 我抢到一个坑,还剩" + semaphore.availablePermits() + "坑位");
                    Thread.sleep(3000);
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

这段程序 创建了一个信号量 控制并发数5个,启动六个线程取上厕所。相当于六个人去抢五个厕所啊!我们看看结果


image.png

2号线程开始没有抢到,被人用完了,才抢到的,要是没有用信号量控制,岂不是2号线程要在别人头上拉屎了吗?

综上:Semaphore 是和用于资源有限的共享情况,比如数据库连接池等。

2、CountDownLatch 计数器

CountDownLatch 是一个计数器,当计数器不到阈值(0)程序会一直等待。CountDownLatch 和Semaphore 提供了一个带有int参数的构造器。提供了一个countDown() (每次调用计数器减一)。他适合在多个任务需要相互协作的场景,比如 王者荣耀 需要五个人才可以开始游戏。我们可以设置一个数量为5的计数器,每一个人进入游戏就countDown 一次,当计数器为0的时候,游戏就可以开始啦。
下面看看用法:

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

        final CountDownLatch countDownLatch = new CountDownLatch(5);

        for (int i = 1; i < 6; i++){
            final int num = i;
            new Thread(() -> {

                System.out.println("我是第" + num +" 个玩家,我进入游戏啦。");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            }).start();
        }
        //等待计数器到达阈值
        countDownLatch.await();
        System.out.println("终于有五个人了啊,开始游戏吧!");
    }

countDownLatch.await() 这个方法会一直等待计数器到达阈值,如果这个方法只有四个人进入游戏,那么这局游戏永远无法开始啦,不信你试试。

3、CyclicBarrier 回环栅栏

之前用游戏这个案例来说明CountDownLatch 的用法,但是我们发现一个很严重的问题,那就是游戏是要一直开始,每五个人就要开始一局的,那么计数器用一次岂不是用不了了? 别担心 我们还有CyclicBarrier 。
CyclicBarrier 在我看来就是一个可以无限使用的计数器,它只要每达到阈值就会重新开始,
下面看看用法吧

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

        String[] arr = {"小明", "小陈", "小牛", "大神", "菜鸡"};
      //CyclicBarrier 构造器 接受两个参数 1、阈值 2、到达阈值后的操作(为空则什么都不做)
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> {
            System.out.println("有五个玩家加入游戏,游戏开始!!!!!!!!");
        });

        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(() -> {
                try {
                    Thread.sleep(new Random().nextInt(10000));
                    System.out.println(Thread.currentThread().getName() + "加入排位,总共有" + (cyclicBarrier.getNumberWaiting() + 1) + "玩家在等待");
                  //回环等待,等到阈值
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }, arr[i / 5]);
            thread.start();
        }
    }

看看结果:


image.png

从结果上看 每五个人进入游戏,CyclicBarrier 就只执行一次 事先内置的任务。
使用上他和CountDownLatch 还是很有很大差别的。CountDownLatch是计算器,只有煮线程在等待计数器结果,其他线程处理完任务就完事了,而CyclicBarrier 是一个屏障,所有的线程遇到屏障都会停下来,等到集齐突破屏障的条件(例子中是五人进入游戏) 在一起处理,并且可以触发事先预留的处理事件(简直就像是集齐七颗龙珠召唤神龙一样 有木有!)。

相关文章

  • 7、那些基于AQS的同步器

    之前说过AQS 是所有同步器的基础,那么我们就来说说那些基于AQS的同步工具吧 1、Semaphore 信号量 S...

  • 深入理解 AQS 和 CAS 原理

    概述 AQS 全称是 Abstract Queued Synchronizer,即抽象队列同步器,AQS内部基于C...

  • AQS

    AQS 的全称是 Abstract Queued Synchronizer,也就是基于队列实现的抽象同步器 AQS...

  • AbstractQueuedSynchronizer 队列同步器

    AbstractQueuedSynchronizer 队列同步器(AQS) 队列同步器 (AQS), 是用来构建锁...

  • Java中的AQS

    1、学习AQS的必要性 队列同步器AbstractQueuedSynchronizer(以下简称同步器或AQS),...

  • 8、AbstractQueuedSynchronizer

    学习AQS的必要性 队列同步器AbstractQueuedSynchronizer(以下简称同步器或AQS),是用...

  • JAVA-AQS

    什么是AQS? 队列同步器AbstractQueuedSynchronizer(以下简称同步器或AQS),就是一个...

  • 现在,就要读懂AQS

    AQS(AbstractQueuedSynchronizer)是JUC中提供的用来构建锁和同步器的框架,基于它,我...

  • JUC原理之AQS

    AQS AQS即AbstractQueuedSynchronizer(抽象队列同步器)。AQS是Reentrant...

  • 2019-04-16——Java 并发包 锁 AQS

    AQS AbstractQueuedSynchronizer简称AQS。是一个用于构建锁和同步器的框架,许多同步器...

网友评论

      本文标题:7、那些基于AQS的同步器

      本文链接:https://www.haomeiwen.com/subject/yqxboftx.html