java JUC 的CountDownLatch,Semaphore,CyclicBarrier的使用

java JUC 的CountDownLatch,Semaphore,CyclicBarrier

起源

一直都只了解过countdownlatch,近期在看redission 实现分布式锁的实现的时候发现了Semaphore。

CountDownLatch的使用

countDownLatch可以作为计数器使用,比如支付,支付需要同时调用很多三方服务,我们为了提升接口的速度,使用多线程同时去获取库存,订单,余额等信息,全部执行完成后再调用真正的下单接口。
执行顺序: 主线程 -》子线程 -》主线程

CountDownLatch 使一个线程A或是组线程A等待其它线程执行完毕后,一个线程A或是组线程A才继续执行
package com.example.springbootmbplus.demo;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ClassName: CountDownLatchDemo
 * @Description: CountDownLatch demo
 * @author: godShan
 * @Date: 2020/6/15 16:29
 */
public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        //老板等待员工完成工作,开始检查任务
        //老板手下有5个员工
        CountDownLatch countDownLatch = new CountDownLatch(5);

        for (int i = 0; i < 5; i++) {
            System.out.println("老板给员工" + (i + 1) + "分配任务");
            executorService.execute(new Worker(countDownLatch));
        }

        //老板等待通知开始检查
        countDownLatch.await();
        executorService.shutdown();
        //老板开始检查工作
        System.out.println("老板开始检查工作");
    }

    /**
     * 员工
     */
    static class Worker implements Runnable {

        private CountDownLatch countDownLatch;

        public Worker(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            System.out.println("员工开始工作 ----------------------");
            countDownLatch.countDown();
            System.out.println("员工完成工作 ----------------------");
        }
    }
}

输出结果:
老板给员工1分配任务
老板给员工2分配任务
老板给员工3分配任务
老板给员工4分配任务
老板给员工5分配任务
员工开始工作 ----------------------
员工开始工作 ----------------------
员工完成工作 ----------------------
员工完成工作 ----------------------
员工开始工作 ----------------------
员工完成工作 ----------------------
员工开始工作 ----------------------
员工完成工作 ----------------------
员工开始工作 ----------------------
员工完成工作 ----------------------
老板开始检查工作

CyclicBarrier的使用

CyclicBarrier主要用来做计数,但是它和CountDownLatch不同。它是通过await方法阻塞子线程,等所有的子线程数量到达后,执行回调任务后子线程再去执行await 之后的代码逻辑。
执行顺序: 主线程 -》子线程 -》主线程的回调任务 -》子线程await阻塞后的代码逻辑

CyclicBarrier:一组线程使用await()指定barrier,所有线程都到达各自的barrier后,再同时执行各自barrier下面的代码
package com.example.springbootmbplus.demo;

import lombok.SneakyThrows;

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ClassName: CyclicBarrierDemo
 * @Description: cyclicBarrier demo
 * @author: godShan
 * @Date: 2020/6/15 15:33
 */
public class CyclicBarrierDemo2 {

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        //老板等待员工完成工作,开始检查任务
        //老板手下有5个员工
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> {
            //老板等待通知开始检查
            //老板开始检查工作
            System.out.println("老板开始检查工作");
        });

        for (int i = 0; i < 5; i++) {
            System.out.println("老板给员工" + (i + 1) + "分配任务");
            executorService.execute(new Worker(cyclicBarrier));
        }

        executorService.shutdown();

    }

    /**
     * 员工
     */
    static class Worker implements Runnable {

        private CyclicBarrier cyclicBarrier;

        public Worker(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }

        @SneakyThrows
        @Override
        public void run() {
            System.out.println("员工开始工作 ----------------------");
            cyclicBarrier.await();
            System.out.println("员工完成工作 ----------------------");
        }
    }

}

输出结果:
老板给员工1分配任务
老板给员工2分配任务
老板给员工3分配任务
老板给员工4分配任务
老板给员工5分配任务
员工开始工作 ----------------------
员工开始工作 ----------------------
员工开始工作 ----------------------
员工开始工作 ----------------------
员工开始工作 ----------------------
老板开始检查工作
员工完成工作 ----------------------
员工完成工作 ----------------------
员工完成工作 ----------------------
员工完成工作 ----------------------
员工完成工作 ----------------------

可以看到 CountDownLatch和CyclicBarrier的区别
1.CountDownLatch的countDown不会去阻塞线程;CyclicBarrier调用await会阻塞线程直到回调的方法执行完成
2.CountDownLatch当计数到0时,计数无法被重置;CyclicBarrier计数达到指定值时,计数置为0重新开始

Semaphore的使用

Semaphore主要是用来做限流的。

Semaphore是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源
package com.example.springbootmbplus.demo;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName: SamphoreDemo
 * @Description: SemaphoreDemo
 * @author: godShan
 * @Date: 2020/6/15 14:37
 */
public class SemaphoreDemo {

    public static void main(String[] args) throws InterruptedException {
        ThreadLocalRandom random = ThreadLocalRandom.current();
        ExecutorService executorService = Executors.newCachedThreadPool();
        //模拟停车位 100个
        Semaphore semaphore = new Semaphore(100);
        //模拟需要停车的数量
        AtomicInteger needSum = new AtomicInteger(0);
        for (int i = 0; i < 2000; i++) {
            TimeUnit.SECONDS.sleep(random.nextInt(0,5));
            System.out.println("第【" + (i + 1) + "】辆车来到停车场入口");
            executorService.execute(() -> {
                try {
                    //占用停车位,内部100-1,如果数量不够了着堵塞
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //总共停车数
                needSum.getAndAdd(1);
                System.out.println("今日第【" + needSum.get() + "】进入停车场");
                System.out.println("停车场剩余车位: 【" + (semaphore.availablePermits()) + "】");
                //todo do something
                try {
                    //模拟逻辑停车时间 5-100秒

                    TimeUnit.SECONDS.sleep(random.nextInt(50,500));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //离开停车场
                semaphore.release();
                System.out.println("有一辆车离开停车场!");
                System.out.println("停车场剩余车位: 【" + (semaphore.availablePermits()) + "】");
            });
        }

        executorService.shutdown();
    }

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值