CountDownLatch、CyclicBarrier、Semaphore多线程协助操作API

目录

Semaphore信号量

CountDownLatch协助线程

CyclicBarrier 循环利用

总结


主要说一下应用场景

Semaphore信号量

 场景:Semaphore 许可证
1、可以限制每个资源同时处理能力 比如:一个API接口、限制只能同时两个线程响应请求,其余的线程需要等待
处理逻辑:
 a.获取线程之后semaphore.acquire() -- 如果没有获取,则会阻塞
 b.用完之后释放 semaphore.release();

场景1:一个API接口,限制同时只能两个线程想相应请求,针对单机版本,可以做限流处理。


public class SemaphoreDemo01 {

    static Semaphore semaphore = new Semaphore(3);

    /**
     * Semaphore 许可证
     * 1、可以限制每个资源同时处理能力 比如:一个API接口、限制只能同时两个线程响应请求,其余的线程需要等待
     * 处理逻辑:
     * a.获取线程之后semaphore.acquire() -- 如果没有获取,则会阻塞
     * b.用完之后释放 semaphore.release();
     * @param args
     */
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            int  finalInt = i ;
            executorService.submit(() -> {
                try {
                    // 获取许可证 如果没有获取,则会阻塞
                    semaphore.acquire();
//                    semaphore.acquire(2); // 可以一次性获取2个授权
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"拿到许可证,耗时2 s");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("慢服务执行完成:"+Thread.currentThread().getName());
                // 释放许可证
                semaphore.release();
            });
        }
        executorService.shutdown();
    }
}

CountDownLatch协助线程

 两种用法:允许一个或多个线程,等待其他一组线程完成操作,再继续执行。

场景1:eg: 比如去查询外部接口API,多个不同类型的API都需要请求

跑步为例,所有runner都需要等待裁判员枪响之后才开始运动


public class CountDownLatchDemo03 {

    /**
     * 运动员 到达终点、所有场景统一汇合之后然后进行
     */
   static CountDownLatch countDownLatch = new CountDownLatch(10);

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            int finalInt = i ;
            executorService.submit(()->{
                try {
                    Thread.sleep((long) (Math.random()*100));
                    countDownLatch.countDown();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("第" + finalInt + "号 到达终点 ");
            });
        }
        System.out.println("等待所有运动员跑完");
        countDownLatch.await();
        System.out.println("所有人都跑完了");
        executorService.shutdown();
    }

}

场景2   

  •  运动员到达终点时,需要知道是否已经所有运动员已经到场了
  • 程序中,比如买机票,针对同一个行程,从不同的航空公司获取对应的票价返回给前端。 

public class CountDownLatchDemo03 {

    /**
     * 运动员 到达终点
     */
   static CountDownLatch countDownLatch = new CountDownLatch(10);

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            int finalInt = i ;
            executorService.submit(()->{
                try {
                    Thread.sleep((long) (Math.random()*100));
                    countDownLatch.countDown();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("第" + finalInt + "号 到达终点 ");
            });
        }
        System.out.println("等待所有运动员跑完");
        countDownLatch.await();
        System.out.println("所有人都跑完了");
        executorService.shutdown();
    }

}

 

CyclicBarrier 循环利用

场景: 多人骑行车、多人坐船

eg:

比如去海边游玩,三人自行车、需要等待三人才能开始,下大巴车之后到海边有一段距离(需要步行,每个人的速度不一样),所以就出现了必须要三个人之后才能启动自行车

public class CyclicBarrierDemo01 {

    // 参数构建 还可以添加其他的
   // 方式1// private static CyclicBarrier cyclicBarrier = new CyclicBarrier(4);
   // 方式2 循环一次(在开闸的时候) 打印一次
    private static CyclicBarrier cyclicBarrier =  new CyclicBarrier(4,()->{
        System.out.println("凑够人数了。 出发!");
    });

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 16; i++) {
            int finalInt = i ;
            System.out.println("第" + finalInt +" 前往,等待启动");
            executorService.submit(()->{
                try {
                    Thread.sleep((long) (Math.random()*1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("第" + finalInt +" 到达驿站,等待启动");
                try {
                    cyclicBarrier.await(10, TimeUnit.SECONDS);// 当不足时,超过时间区间。则会抛出异常
                    System.out.println("第" + finalInt +" 开始骑车");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                } catch (TimeoutException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
    }

}

总结

# Semaphore 信号量
1、控制用户请求的数量。比如限制2个线程进入,其余的线程则需要等待,直到某个线程完成才会重新进入新的线程工作
# CountDownLatch 
用法1:
  主线程等待-多个子线程执行完成之后一起执行
   eg: 比如去查询外部接口API,多个不同类型的API都需要请求, 
   **1.api1 2.api2 3.api3**
   一般做法: 一次调用api1、api2、api3
   同时调用 :多线程调用api1、api2、api3
   最后主线程等待即可
   
用法2:
  多个线程等待某一个线程信号,同时开始执行
    eg: 同时5个线程同时争夺某个资源
    一般在测试类中使用

# CyclicBarrier 循环使用场景
场景:
  比如 划船,必须4个人一组,否则不允许开船,并且可以循环执行

代码连接地址 demo链接

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值