CountDownLatch解析

CountDownLatch简介

CountDownLatch是一个同步辅助工具类,它允许一个或多个线程等待直到其他线程中一系列操作完成。latch有闭锁的意思,所以CountDownLatch又称闭锁。
CountDownLatch初始化时必须给定一个count值,用来表示事件总数。每次调用countDown方法事件数就会减一,只要count值不为0线程就会一直处于等待状态或者等待线程超时及中断。等到count值为0时,await方法就是释放,此时所有的线程开始运行。
countDownLatch就像田径比赛一样,当每有一个运动员准备完毕计数器就减一,等到所有人都准备完毕之后,发令枪一响所有运动员开跑,谁跑的最快谁就优先获取到CPU的执行权。
CountDownLatch必须在初始化时指定count值,而且count值一旦被初始化之后不能再重新设置值。
如果需要可变的版本可以考虑使用CyclicBarrier。

CountDownLatch使用场景

1、确保一个服务不会开始,直到其依赖的其他服务都已经开始。每一个服务都包含一个二元闭锁,开启服务S首先会等待闭锁S依赖的其他服务,在启动结束后,这些所有依赖S的服务也都可以处理了。
2、等待,直到所有活动部分都已为继续处理做好准备,比如王者荣耀或者英雄联盟这类游戏,在匹配玩家的时候只有所有玩家都确认之后才能到选择英雄界面,也就是终点状态。
诸如此类的问题的都可以使用CountDownLatch。

CountDownLatch使用

CountDownLatch方法

CountDownLatch中主要用到的方法有三个:
1、countDown():减少闭锁的count值,当count值到达0时,释放所有等待中的线程。
2、await() :当前线程会处于等待状态,知道count值为0,除非当前线程中断否则会一直等待。当count为0时,await方法会立即返回。如果count值大于0,当前线程就不会被调度并且处于休眠状态,除非以下两种情况发生:
1、count值到达0;
2、其他线程中断了当前线程。
3、await(long timeout, TimeUnit unit) :当count到达0时返回true,当超过等待时间后返回false;该方法和无参的await方法一样,只不过就是多了等待时间而已。

例子:

public class CountDownDemo {
    private static final int N = 5;
    private static CountDownLatch countDownLatch = new CountDownLatch(N);

    private static class ServiceThread implements Runnable{
        @Override
        public void run() {
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getId()+" await.....");
        }
    }

    private static class CountDownThread implements Runnable{

        @Override
        public void run() {
            countDownLatch.countDown();
            System.out.println(Thread.currentThread().getId()+" countDown.....");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("MainThread start");
		 new Thread(new ServiceThread()).start();
        for (int i = 0; i < N - 1; i++) {
         new Thread(new CountDownThread()).start();
        }
        countDownLatch.countDown();
        countDownLatch.await();
        System.out.println("MainThread end");
    }
}

运行结果:

MainThread start
11 countDown.....
12 countDown.....
13 countDown.....
14 countDown.....
MainThread end
15 await.....

N初始化为5个,代表有5个线程进行处理,ServiceThread调用await阻塞当前线程运行,CountDownThread 对count进行递减。
从打印结果可以看出,ServiceThread虽然先启动了,但是却一直在阻塞处于等待状态,当count值递减到0是才变成运行状态。当把循环外的countdown方法注释掉,线程会一直处于等待状态,直到count值变为0。

posted @ 2022-04-29 19:05  码猿笔记  阅读(185)  评论(0编辑  收藏  举报