并发类编程—CountDownLatch(同步器)

导读:本篇文章讲解 并发类编程—CountDownLatch(同步器),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

1、概述

CountDownLatch是一个同步器工具类,用来协调多个线程之间的同步,能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行,不可重置使用。

2、实现

使用一个计数器进行实现,计数器初始值为线程的数量,当每一个线程完成自己任务后,计数器的值就会减一,当计数器的值为0时,在CountDownLatch上等待的线程就可以恢复执行接下来的任务。

3、缺点

CountDownLatch是一次性的,计算器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当CountDownLatch使用完毕后,它不能再次被使用。

4、方法说明:

  • public void countDown():递减锁存器的计数,如果计数到达零,则释放所有等待的线程。如果当前计数大于零,则将计数减少.
  • public viod await() /boolean await(long timeout,TimeUnit unit) :使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。如果当前计数为零,则此方法立刻返回true值。当线程调用了CountDownLatch对象的该方法后,当前线程会被阻塞,直到下面的情况之一发生才会返回:
    • 如果计数到达零,则该方法返回true值。
    • 如果当前线程,在进入此方法时已经设置了该线程的中断状态;或者在等待时被中断,则抛出InterruptedException,并且清除当前线程的已中断状态。
    • 如果超出了指定的等待时间,则返回值为false。如果该时间小于等于零,则该方法根本不会等待。参数:timeout-要等待的最长时间、unit-timeout 参数的时间单位

5、使用用法

  • 某一线程在开始运行前等待n个线程执行完毕
  • 多个线程开始执行任务的最大并行性(多个线程等待一个线程执行完成)

5.1 方法一

某一线程在开始运行前等待n个线程执行完毕,为某一个线程设置await(),当CountDownLatch为0时,执行当前线程。

public class Test {
    /**
     * 设置计数器大小为5
     */
    private static CountDownLatch latch = new CountDownLatch(5);

    public static void loading(int num) {
        System.out.println("计数器数量为:" + num);
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        latch.countDown();
    }

    public static void main(String[] args) {
        new Thread(() -> {
            for (int i = 5; i >= 1; i--) {
                loading(i);
            }
        }, "t1").start();


        // 等待5个t1线程执行完成
        try {
            latch.await();
            System.out.println("执行主线程");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

效果:
在这里插入图片描述

5.2 方法二

实现多个线程开始执行任务的最大并行性,比如设置CountDownLatch()初始化值为1,多个线程同时进行countdownlatch.await(),到计数器值为0时多个线程同时运行(多个线程等待其他线程执行完成后再执行)。

public class Test {
    /**
     * 设置计数器大小为1
     */
    private static CountDownLatch latch = new CountDownLatch(1);

    public static void main(String[] args) {
        for (int i = 5; i >= 1; i--) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "-准备中");
                    latch.await();
                    System.out.println(Thread.currentThread().getName() + "-已完成");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }

        // 等待一秒,让其他线程做好准备
        try {
            TimeUnit.SECONDS.sleep(1);
            System.out.println("执行主线程");
            latch.countDown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

效果:
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/18089.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!