JUC包中的 CountDownLatch/CyclicBarrier/Semaphore

目录

1. CountDownLatch

1.1 概念

1.2 CountDownLatch方法(2个)

1.3 DEMO

1.3.1 DEMO-使用之前

1.3.2 DEMO-使用之后

1.3.3 DEMO-生活案例,秦灭六国,一统华夏

2 CyclicBarrier

2.1 概念

​2.2 DEMO

3 Semaphore(信号灯,信号量)

3.1 概念

3.2 使用场景

3.3 DEMO

4 参考文献


1. CountDownLatch

1.1 概念

让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒。

1.2 CountDownLatch方法(2个)

当一个或多个线程调用await方法时,调用线程会被阻塞。

其他线程调用countDown方法会将计数器减一(调用countDown方法不会被阻塞)

当计数器的值变为0时,因调用await方法被阻塞的线程会被唤醒,继续执行

1.3 DEMO

1.3.1 DEMO-使用之前

以锁门为例,班长需要6位同学都离开教室才可以关门离开

public class CountDownLatchDemo {
    public static void main(String[] args) throws Exception{
        for (int i = 0; i < 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName()+"\t 上完自习,离开教师");
            }, String.valueOf(i)).start();
        }
        System.out.println(Thread.currentThread().getName()+"\t ************班长最后关门走人");
    }
}

输出

0     上完自习,离开教师
main     ************班长最后关门走人
2     上完自习,离开教师
3     上完自习,离开教师
5     上完自习,离开教师
4     上完自习,离开教师
1     上完自习,离开教师

会发现此时,班长关门时间错误

1.3.2 DEMO-使用之后

public class CountDownLatchDemo {
    public static void main(String[] args) throws Exception {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 0; i < 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t 上完自习,离开教师");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "\t ************班长最后关门走人");
    }
}

输出

0     上完自习,离开教师
3     上完自习,离开教师
1     上完自习,离开教师
2     上完自习,离开教师
5     上完自习,离开教师
4     上完自习,离开教师
main     ************班长最后关门走人

1.3.3 DEMO-生活案例,秦灭六国,一统华夏

public class CountDownLatchDemo {
    public static void main(String[] args) throws Exception {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "国,被灭");
                countDownLatch.countDown();
            }, CountryEnum.getMessageByCode(i)).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "\t ************秦帝国,一统华夏");
    }
}

//国家枚举类
public enum CountryEnum {
    ONE(1, "齐"),
    TWO(2, "楚"),
    THREE(3, "燕"),
    FOUR(4, "赵"),
    FIVE(5, "魏"),
    SIX(6, "韩");

    Integer retCode;
    String retMessage;

    CountryEnum(int retCode, String retMessage) {
        this.retCode = retCode;
        this.retMessage = retMessage;
    }

    public static String getMessageByCode(int code) {
        for (CountryEnum countryEnum : CountryEnum.values()) {
            if (countryEnum.getRetCode() == code) {
                return countryEnum.getRetMessage();
            }
        }
        return "未找到国家";
    }

    public Integer getRetCode() {
        return retCode;
    }

    public void setRetCode(Integer retCode) {
        this.retCode = retCode;
    }

    public String getRetMessage() {
        return retMessage;
    }

    public void setRetMessage(String retMessage) {
        this.retMessage = retMessage;
    }
}

输出

齐国,被灭
燕国,被灭
楚国,被灭
魏国,被灭
赵国,被灭
韩国,被灭
main     ************秦帝国,一统华夏

2 CyclicBarrier

和CountDownLatch(减法)相反,是增加到指定数量,才可以做某件事,做加法。

例:集齐7颗龙珠,召唤神龙; 人到齐了才开会

2.1 概念

字面意思:可循环(Cyclic)使用的屏障(Barrier)

让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截多线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法

2.2 DEMO

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> System.out.println("*****召唤神龙"));

        for (int i = 1; i <= 7; i++) {
            final int tempInt = i;
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t 收集到第" + tempInt + "龙珠");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }
    }
}

3 Semaphore(信号灯,信号量)

3.1 概念

信号量主要用于两个目的,

一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制

即,多线程,资源用完时,其他未抢到资源的线程等待,前面每释放一个资源,就抢一个资源。

特点:加,减,资源空间伸缩

可代替synchonized和lock

Semaphore(int permits, boolean fair)

permits 资源数量

fair:公平、非公平

3.2 使用场景

争车位;支付接口常用;netty 底层

dubbo 底层 rpc

rpc 底层 nio

3.3 DEMO

public class SemaphoreDemo {
    public static void main(String[] args) {
        //模拟3个停车位
        Semaphore semaphore = new Semaphore(3);

        //模拟6个车子
        for(int i = 1; i <= 6; i++) {
            new Thread(() -> {
                try {
                    //占车位
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "\t 抢到车位");
                    try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
                    System.out.println(Thread.currentThread().getName() + "\t 停车3秒后离开车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                }
            }, String.valueOf(i)).start();
        }
    }
}

输出

1     抢到车位
3     抢到车位
2     抢到车位
3     停车3秒后离开车位
2     停车3秒后离开车位
4     抢到车位
1     停车3秒后离开车位
5     抢到车位
6     抢到车位
6     停车3秒后离开车位
5     停车3秒后离开车位
4     停车3秒后离开车位

当车位满了的时候,其他线程车在等待,有车位被空出时,才有下一个车进来停车

4 参考文献

以上内容均来自于下方视频,博客内容仅作为个人学习笔记记录

【1】Java面试_高频重点面试题 (第一、二、三季)_ 面试 第1、2、3季_柴林燕_周阳_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值