> 文档中心 > 并发类编程—CountDownLatch(同步器)

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


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(); }    }}

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

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(); }    }}

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