• Java面试题13-CountDownLatch和Semaphore的区别和底层原理


    CountDownLatch和Semaphore的区别和底层原理

    CountDownLatch

    CountDownLatch表示计数器,可以给CountDownLatch设置一个数字,一个线程调用CountDownLatchawait()将会被阻塞,其他线程可以调用CountDownLatchcountDown()方法来对CountDownLatch中的数字减一,当数字被减为0后,所有的await的线程将会被唤醒。

    对应的底层原理就是,调用await()方法的线程会利用AQS排队,一旦数字被减为0,则会将AQS中的排队的线程依次唤醒。

    ​countDownLatch.countDown(); 数量-1。
    countDownLatch.await(); 等待计数器归零,然后再向下执行。
    每次有线程调用countDown()数量-1,如果计数器变为0,countDownLatch.await()就会被唤醒,继续执行。

    在这里插入图片描述

    public class CountDownLatchTest {
        public static void main(String[] args) throws InterruptedException {
            //总数是6,必须要执行任务的时候,在使用
            CountDownLatch countDownLatch = new CountDownLatch(6);
            for (int i = 0; i < 6; i++) {
                new Thread(()->{
                    System.out.println(Thread.currentThread().getName() + "Go out");
                },String.valueOf(i)).start();
            }
            //等待计数器归零,再向下执行
            countDownLatch.await();
            System.out.println("Close Door");
        }
    }
    如果没有countDownLatch.await();的时候,输出结果可能为:
    	Close Door
        3Go out
        2Go out
        5Go out
        1Go out
        4Go out
        0Go out
    加了countDownLatch.await();之后,就会等待所有线程结束之后进行执行:
        1 Go out
        5 Go out
        4 Go out
        3 Go out
        2 Go out
        6 Go out
    	Close Door
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    Semaphore

    Semaphore表示信号量,可以设置许可的个数,表示同时允许最多多少个线程使用该信号量,通过acquire()来获取许可,如果没有许可可用则线程阻塞,并通过AQS来排队,可以通过release()方法来释放许可,当某个线程释放了某个许可后,会从AQS中正在排队的第一个线程开始依次唤醒,直到没有空闲许可。

    semaphore.acquire(); 获得,如果已经满了,就等待,等待被释放为止。
    semaphore.release(); 释放,会将当前的信号量释放 +1,然后唤醒等待的线程。

    在这里插入图片描述

    public class SemaphoreTest {
        public static void main(String[] args) {
            //线程数量:停车位例子!  限流的时候可以这样使用
            //相当于在有限的资源情况下,让合理的应用
            Semaphore semaphore = new Semaphore(3);
    
            for (int i = 1; i <= 6 ; i++) {
                new Thread(()->{
                    try {
                        //获得
                        semaphore.acquire();
                        System.out.println(Thread.currentThread().getName() + "抢到车位");
                        TimeUnit.SECONDS.sleep(2);
                        System.out.println(Thread.currentThread().getName() + "离开车位");
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }finally {
                        //释放
                        semaphore.release();
                    }
                },String.valueOf(i)).start();
            }
        }
    }
    输出结果:
    	1抢到车位
        3抢到车位
        2抢到车位
        3离开车位
        1离开车位
        6抢到车位
        4抢到车位
        2离开车位
        5抢到车位
        4离开车位
        5离开车位
        6离开车位	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    RK3568驱动指南|第六篇-平台总线-第54章 点亮LED灯实验
    HDFS 分布式环境搭建
    RabbitMQ实现数据库与ElasticSearch的数据同步和分享文件过期处理
    新能源汽车高压线束是如何快速连接到测试设备上进行电性能测试的
    [附源码]计算机毕业设计JAVAjsp毕业设计管理系统
    2023年“羊城杯”网络安全大赛 Web方向题解wp 全
    玩转Matlab-Simscape(初级)- 10 - 基于COMSOL&Simulink 凸轮机构的控制仿真
    elasticSearch的索引库文档的增删改查
    读懂这篇,让你了解CRM核心功能
    【DL】关于tensor(张量)的介绍和理解
  • 原文地址:https://blog.csdn.net/z318913/article/details/126788543