CountDownLatch工具类的示例与理解

CountDownLatch是一个同步工具类,用于线程间的协调,例如在所有线程执行完毕后再继续执行某个线程。它有一个计数器,初始值为线程数量,每完成一个线程任务,计数器减一,当计数器为0时,所有等待的线程会被释放。CountDownLatch的主要方法有构造器、getCount、countDown和await。其优点是简单灵活,但缺点是一次性使用且不支持中断。

一、CountDownLatch是什么

        CountDownLatch是一个同步工具类,可以使一个或多个线程等待其他线程执行结束后再执行。举个例子来说,五个人跑步比赛,我们等待五个人都越过终点后再进行统计成绩。

        CountDownLatch中定义了一个计数器,初始值为其他线程的数量,按照上面的例子,我们就应该将其定义为5,当一个人冲过终点,也就是一个线程执行完毕后,就将其减一,当五个人都冲过终点后,此时值为0,当计数器达到0时,表示其他线程执行完毕,等待的线程就可以恢复执行。

二、CountDownLatch的方法

  1. CountDownLatch(int count):count为计数器的初始值。
  2. getCount():获取当前计数器的值。
  3. countDown(): 计数器的值-1,直到count为0。
  4. await(): 等待计数器变为0。
  5. boolean await(long timeout, TimeUnit unit),与await()类似
    参数:timeout,等待时间;unit,时间单位。指定等待时间,若超时则自动唤醒其他线程。
    返回值:boolean类型,若等待超时则返回false,否则返回true

三、CountDownLatch的示例

/**
 * 五人比赛跑步,结束后统计数据
 */
public class Test01 {

    //选手数量
    public static final int RUNNER = 5;
    //裁判
    public static final int REFEREE = 1;
    //时间计数
    public static Long startTime;

    public static void main(String[] args) {
        //获取核心数
        int cpuNum = Runtime.getRuntime().availableProcessors();
        //创建线程池
        ExecutorService executorService = new ThreadPoolExecutor(cpuNum * 2, cpuNum * 2,
                0, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        //创建选手的同步计数器,count为5
        CountDownLatch runLatch = new CountDownLatch(RUNNER);
        //创建裁判的同步计数器,count为1
        CountDownLatch refereeLatch = new CountDownLatch(REFEREE);
        //创建五个线程,即五个选手
        for (int i = 0; i < RUNNER; i++) {
            //每个选手
            executorService.execute(() -> {
                try {
                    System.out.println("选手" + Thread.currentThread().getName() + " 等待比赛开始");
                    //选手等待裁判
                    refereeLatch.await();
                    System.out.println("选手" + Thread.currentThread().getName() + " 起跑");
                    Thread.sleep((long) (8000 + Math.random() * 5000));
                    System.out.println("选手" + Thread.currentThread().getName() + " 到达终点"
                            + " 耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    //选手到达终点,计数器减一
                    runLatch.countDown();
                }
            });
        }
        try {
            //比赛开始倒计时
            for (int i = 5; i > 0; i--) {
                Thread.sleep(1000);
                System.out.println(i);
            }
            Thread.sleep(1000);
            //比赛开始
            System.out.println("比赛开始");
            startTime = System.currentTimeMillis();
            //唤醒5个选手
            refereeLatch.countDown();
            //裁判等待选手都到达终点
            runLatch.await();
            System.out.println("所有选手到达终点,比赛结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executorService.shutdown();
    }
}

执行结果

 

四、CountDownLatch的优缺点

优点:使用起来较为简单,比较灵活,线程安全。

缺点:只支持使用一次,且不支持中断。
           计数器的值只支持在构造方法中初始化一次,之后没有任何地方可以再次对其进行设置,
           当CountDownLatch被使用完后,无法重复使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值