Redisson——RCountDownLatch倒计数器(闭锁)

# 倒计数器场景

一个线程等待一组线程的执行

例如手机安装软件前的每一步,授权,确认等;或者班长等剩下6名同学出来才能锁门……

# JUC的CountDownLatch

执行原理,我们通过await方法把需要执行的逻辑给阻塞住,然后CountDownLatch的量要减为0后才能执行。

    //把这个main线程想象成关门的人
    public static void main(String[] args) throws InterruptedException {
        //模拟锁门,需要等6位同学出来才能锁门
        CountDownLatch countDownLatch = new CountDownLatch(6);
        //模拟6名同学
        for (int i = 0; i < 6; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "准备出门。。");
                    //墨迹一会
                    TimeUnit.SECONDS.sleep(new Random().nextInt(5));
                    System.out.println(Thread.currentThread().getName() + "出门了");
                    //每出来一名同学,释放一次资源
                    countDownLatch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, i + "号同学").start();
        }
        //在这6名同学出来之前,需要对关门的人进行阻塞
        countDownLatch.await();
        //等6名同学都出来了,可以锁门了
        System.out.println(Thread.currentThread().getName() + "可以锁门了");
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
0号同学准备出门。。
5号同学准备出门。。
4号同学准备出门。。
3号同学准备出门。。
2号同学准备出门。。
1号同学准备出门。。
4号同学出门了
1号同学出门了
0号同学出门了
3号同学出门了
2号同学出门了
5号同学出门了
main可以锁门了
1
2
3
4
5
6
7
8
9
10
11
12
13

# Redisson的RCountDownLatch

基于Redisson的Redisson分布式闭锁(CountDownLatch (opens new window))Java对象RCountDownLatch采用了与java.util.concurrent.CountDownLatch相似的接口和用法。

RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.trySetCount(1);
latch.await();

// 在其他线程或其他JVM里
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.countDown();
1
2
3
4
5
6
7

# 代码实现RCountDownLatch

编写两个接口,分别为主线程方法和需要等待释放的线程方法,执行逻辑:

  1. 请求latch接口会被阻塞
  2. 需要执行counDown接口的方法,使得资源量减为0,latch接口才会被放行
@GetMapping("/test/latch")
    public String testLatch() {
        stockService.testLatch();
        return "锁门了!";
    }

    @GetMapping("/test/countDown")
    public String testCountDown() {
        stockService.testCountDown();
        return "出来了一位同学";
    }
1
2
3
4
5
6
7
8
9
10
11

编写对应的业务方法:

    /**
     * 主任务(资源释放为0才能被执行)
     */
    public void testLatch() {
        RCountDownLatch cdl = redissonClient.getCountDownLatch("cdl");
        cdl.trySetCount(6);
        try {
            cdl.await();
            //TODO:一系列操作 准备锁门
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 一组任务(执行完这组任务才能出发主任务的执行)
     */
    public void testCountDown() {
        RCountDownLatch cdl = redissonClient.getCountDownLatch("cdl");
        //TODO:一系列操作 然后资源减一
        cdl.countDown();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22