Java中的CountDownLatch是干啥用的?

发布于 2022-11-14  239 次阅读


简介

  1. CountDownLatch一般用作多线程倒计时计数器,强制它们等待其他一组(CountDownLatch的初始化决定)任务执行完成。
  2. 有一点要说明的是CountDownLatch初始化后计数器值递减到0的时候,不能再复原的,这一点区别于SemaphoreSemaphore是可以通过release操作恢复信号量的。

使用说明

  1. 创建CountDownLatch并设置计数器值。
  2. 启动多线程并且调用CountDownLatch实例的countDown()方法。
  3. 主线程调用 await() 方法,这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务,count值为0,停止阻塞,主线程继续执行。

For Example

package org.examples.example;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class CountDownLatchTest {

    //线程总数
    private static int N = 10;

    // 单位是分钟
    private static int countDownLatchTimeout = 5;

    public static void main(String[] args) {
        //创建CountDownLatch并设置计数值,该count值可以根据线程数的需要设置
        CountDownLatch countDownLatch = new CountDownLatch(N);
        //创建线程池
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < N; i++) {
            cachedThreadPool.execute(() ->{
                try {
                    System.out.println(Thread.currentThread().getName() + " do something!");
                } catch (Exception e) {
                    System.out.println("Exception: do something exception");
                } finally {
                    //该线程执行完毕-1
                    countDownLatch.countDown();
                }
            });
        }
        System.out.println("主线程-1");
        try {
//            导致当前线程等待,直到闩锁倒计时到零,除非线程被中断,或指定的等待时间已过。
//            如果当前计数为零,则该方法立即返回值为true。
//            如果当前计数大于零,那么当前线程将被禁用,并处于休眠状态,
//            直到发生以下三种情况之一:由于调用了countDown方法,计数达到零;或其他线程中断当前线程;或指定的等待时间已过。
            countDownLatch.await(countDownLatchTimeout, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            System.out.println("Exception: await interrupted exception");
        } finally {
            System.out.println("countDownLatch: " + countDownLatch.toString());
        }
        System.out.println("主线程-2");
        // 关闭/停止线程池
        // cachedThreadPool.shutdown();

    }
}