简单理解并发包下的CountDownLatch、CyclicBarrier、和Semaphore

本文深入探讨了Java中三种核心的多线程同步机制:CountDownLatch、CyclicBarrier和Semaphore。通过具体场景如电影院观影、过山车启动及商场试衣间的使用,形象地解释了这些同步工具的工作原理及其在并发编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

简单记录自己平常写代码的case, 写代码最重要的就是学习思想,欢迎讨论。

CountDownLatch

多线程交互中用的最多的就是CountDownLatch, 可以根据源码单步调试一下,提高自己的阅读源码的能力。
场景:电影院看电影散场,一共六个人观看,管理员在电影播放完毕,游客散去以后关闭影院大门。

public static void main(String[] args) throws Exception{
        CountDownLatch countDownLatch = new CountDownLatch(6);
        // 模拟6个游客在影院看电影
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "离开影院");
                // 走一个人,countDownLatch减少1,直到变为零
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }

        System.out.println("管理员" + Thread.currentThread().getName() + "等待关门");
        // 管理员时刻监控countDownLatch的值,变为零的时候证明游客已全部离开
        countDownLatch.await();
        System.out.println("管理员" + Thread.currentThread().getName() + "关门成功");
    }
CyclicBarrier

场景:相比于CountDownLatch, CyclicBarrier要表达的是,类似于坐过山车,一共有十个位置,直到人凑齐了,这辆过山车才会启动。(商家为了赚钱规定只有坐满人才发动过山车)

/*demo1*/
public static void main(String[] args) {
        // 模拟3个线程到达屏障点,才触发一次屏障操作
        // 第二个参数设置的是当有3个线程准备好的时候,要触发的屏障操作
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {
            System.out.println(Thread.currentThread().getName() + "触发一次屏障操作");
        });
        for (int i = 0; i < 9; i++) {
            final int tempInt = i;
            // 模拟线程准备时间(doSomething()...)
            try {
                    TimeUnit.SECONDS.sleep(tempInt);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            new Thread(() -> {
                System.out.println("线程" + tempInt + "准备就绪");
                try {
                	// 等待其他线程准备就绪
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }
    }
/*demo2*/
public static void main(String[] args) {
        // 模拟3个线程到达屏障点(准备完毕)才触发一次屏障(过山车)操作
        // 和上个CyclicBarrier的demo不同的是,第二个参数不设置
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        for (int i = 0; i < 9; i++) {
            final int tempInt = i;
            // 模拟线程准备时间
            new Thread(() -> {
                try {
                    TimeUnit.SECONDS.sleep(tempInt);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程" + tempInt + "准备完成");
                try {
                	// 当返回参数为零时,表示满足触发屏障条件
                    if (cyclicBarrier.await() == 0) {
                    	// 最后一个到达屏障点的线程进行屏障操作
                        System.out.println("线程" + Thread.currentThread().getName() + "触发屏障操作");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();

        }
    }
Semaphore

场景:例如去商场买衣服,去试衣间试衣服,一共有五个试衣间,进去试衣间,把门锁上,试衣服,试完后,打开门出来。别人可以接着用这个试衣间(试衣间可以看做共享资源,同时只能有一个人占有)

public static void main(String[] args) {
        // 默认为非公平的获取方式
        // 例如去商场买衣服,去试衣间试衣服,一共有五个试衣间,当参数为true时,表示使用先进先出的FIFO算法保证先acquire的线程先获取许可进入
        // 当参数为false时,表示线程可以加塞到先获取acquire的线程钱获取许可
        Semaphore semaphore = new Semaphore(5, true);
        // 假如有十个人要试衣服,使用商场公有的试衣间
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "同学进入试衣间成功!!!");
                try {
                    // 模拟某个同学占用了试衣间多久时间
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "同学离开试衣间!!!");
                semaphore.release();
            }, String.valueOf(i)).start();
        }
    }

有哪里不对的指出来,大家共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值