CountDownLatch/CyclicBarrier/Semaphore介绍

本文介绍了Java并发控制的三种工具:CountDownLatch用于等待所有线程执行完毕再继续,CyclicBarrier则是在所有线程到达指定点后一起继续,Semaphore用于限制线程并发数。通过实例展示了它们在并发场景中的应用,帮助理解其工作原理和使用方法。
摘要由CSDN通过智能技术生成


CountDownLatch

CountDownLatch的作用就是保证其他的线程都执行完毕,主线程才会执行,只要有一个线程没有执行完毕,主线程都需要等待此线程执行完毕后才能执行。

场景:加入一个班里有5个人,班长必须等到所有的人离开了教室之后才可以锁门。

下面看一下代码模拟这个场景:

public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {

            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "上完自习,离开教室!");
            },String.valueOf(i)).start();
        }

        System.out.println("班长锁门了!");
    }

执行结果:

0上完自习,离开教室!
3上完自习,离开教室!
2上完自习,离开教室!
班长锁门了!
1上完自习,离开教室!
4上完自习,离开教室!

假如这个事情发生在了生活中,估计1号和4号同学会打班长一顿吧。

那么这个问题就需要使用CountDownLatch来解决了。

public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {

            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "上完自习,离开教室!");
                 // 一个同学离开教室之后,countDownLatch减少1
                countDownLatch.countDown();
            },String.valueOf(i)).start();
           
        }
        // 保证countDownLatch减为0,否则会一直等待
        countDownLatch.await();
        System.out.println("班长锁门了!");
    }

输出结果:

0上完自习,离开教室!
1上完自习,离开教室!
2上完自习,离开教室!
3上完自习,离开教室!
4上完自习,离开教室!
班长锁门了!

这样孩子们就可以吃上麻麻做的香喷喷的饭了!

总结:让一些线程阻塞知道另一些线程完成一系列操作后才被唤醒。
CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,调用线程会被阻塞。其他线程调用countDown方法会将计数器减1,(调用countDown方法的线程不会被阻塞),当计数器的值变为0时,因调用await方法被阻塞的线程会被唤醒,继续执行。

CyclicBarrier

CyclicBarrier正好和CountDownLatch相反,是做加法,就像是集齐了七颗龙珠才能召唤神龙。
CyclicBarrier的字面意思是可循环使用的屏障,他要做的事情是让一组线程到达 一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程达到屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await方法。

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

        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> System.out.println("召唤神龙!"));

        for (int i = 1; i <= 7; i++) {
            int finalI = i;
            new Thread(() -> {
                System.out.println("收集到" + finalI + "星球!");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }

            }).start();


        }
        
    }

运行结果:

收集到1星球!
收集到3星球!
收集到2星球!
收集到4星球!
收集到5星球!
收集到6星球!
收集到7星球!
召唤神龙!

Semaphore

Semaphore 是 synchronized 的加强版,作用是控制线程的并发数量。就这一点而言,单纯的synchronized 关键字是实现不了的。你可以把Semaphore当成前台的管理人员,他的作用就是调度客人,假如我们去海底捞吃饭,很不巧,我们去的时候已经满了,需要等位,前台会给我们一个号码等待叫号,有一桌客人吃完管理人员通知下一个等号的人进去吃饭。

场景: 假如一个停车场有三个停车位,现在有6辆车需要停车,那这样的话肯定有3辆车需要等待,假如进入停车场的车每辆停3秒,3秒后离开停车场,这样剩余的3辆车就会有空余的车位进行停车。

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

        Semaphore semaphore = new Semaphore(3);
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                try {
                    // 占车位
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "进场!");
                    // 停车3秒
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(Thread.currentThread().getName() + "离开!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally {
                    // 释放车位
                    semaphore.release();
                }
            },String.valueOf(i)).start();
        }

    }

运行结果:

1进场!
2进场!
3进场!
2离开!
1离开!
4进场!
3离开!
5进场!
6进场!
4离开!
6离开!
5离开!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

壹升茉莉清

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值