【JDK 5】JUC 同步类 限流:Semaphore、CountdownLatch、CyclicBarrier

作用: 限流


一、Semaphore 作用:限制访问资源的线程数量

创建

构造器参数
Semaphore(int n)n:信号量
Semaphore(int n,boolean p)n:信号量,p:是否公平

使用

//创建信号量为2的Semaphore,可同时让两个线程访问
Semaphore semaphore = new Semaphore(2);
//获取信号,信号量-1, 
semaphore.acquire();
/** 代码逻辑 **/
//释放信号,信号量+1,释放信号
semaphore.release();

若超过信号量2,其他线程进入队列等待


二、CyclicBarrier

作用: 访问线程达到指定数量时,执行await之后的代码

使用

CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
for (int i = 0; i < 10; i++) {
    new Thread(()->{
        try {
            System.out.println("等待");
            cyclicBarrier.await();
            //代码逻辑
            System.out.println("执行任务完毕");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }).start();
}

注意:
线程数没有达到指定数量时,await会一直等待。

若需要限时且不想一直等待,可以使用cyclicBarrier.await(时间,时间单位),这样超时就会抛异常


三、CountdownLatch

作用:当计数器达到0时,执行await之后的代码

CountdownLatch可以实现CyclicBarrier的功能(正常不会这样用的,因为已经有CyclicBarrier了)

CountDownLatch countdownLatch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
    new Thread(()->{
        try {
            //count减1
            countdownLatch.countDown();
            //等待计数为0
            countdownLatch.await();
            System.out.println("执行任务");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }).start();
}

CountdownLatch与CyclicBarrier的区别:

CountdownLatch一次性CyclicBarrier可调用reset重复使用
最大的区别是CountdownLatch还可以实现N个任务线程await等待其他线程完成countDown后,继续执行任务线程

例子

以下是3个任务线程 等待5个线程完成countDown后,继续执行3个任务线程

    CountDownLatch countdownLatch = new CountDownLatch(5);
    //5个执行A任务的线程
    for (int i = 0; i < 5; i++) {
        new Thread(()->{
            //代码逻辑
            System.out.println("A任务逻辑");
            countdownLatch.countDown();
        }).start();
    }
    //3个执行B任务的线程
    for (int i = 0; i < 3; i++) {
        new Thread(()->{
            try {
                //等待A任务完成
                countdownLatch.await();
                System.out.println("B任务逻辑");
                //代码逻辑
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();
    }

注意:
计数器不为0,await会一直等待。

若需要限时且不想一直等待,可以使用cyclicBarrier.await(时间 , 时间单位 ),这样超时就会抛异常


底层实现

AQS( Abstract Queued Synchronizer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码鹿的笔记

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

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

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

打赏作者

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

抵扣说明:

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

余额充值