CountDownLatch 学习笔记

发布时间 2023-04-23 23:27:42作者: shine-rainbow

1. 概念

CountDownLatch是在JDK 1.5的时候被引入的,位于java.util.concurrent并发包中,CountDownLatch叫做闭锁,也叫门闩。允许一个或多个线程一直等待,直到其他线程执行完成后再执行。

2.工作原理

CountDownLatch通过一个计数器来实现的。计数器的初始化值为线程的数量。每当一个线程完成自己的任务后,计数器的值就相应的减1.当计数器的值减到0时,表示所有的线程都已经完成任务。然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。

3. 常见方法

  • public CountDownLatch(int count)

​ CountDownLatch接收一个int型参数,表示要等待的工作线程的个数。

  • public void await()

​ 使用当前线程进入同步队列进行等待,直到计数器的值减到0或者当前线程被中断,当前线程就会被唤醒。

  • public boolean await(Long timeout,TimeUnit unit)
@Slf4j
public class CountDownLatchTest {
    //线程总数
    private final static int threadCount = 200;

    public static void main(String[] args) throws Exception {
        //创建固定线程数的线程池
        ExecutorService exec = Executors.newFixedThreadPool(threadCount);
        //如果有n个子线程,则指定CountDownLatch的计数器为n
        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);

        //提交到线程池
        for (int i = 0; i < threadCount; i++) {
            exec.execute(()->{
                try{
                    System.out.println("子线程:"+Thread.currentThread().getName()+"开始执行");
                    //模拟每个线程处理业务,耗时一秒钟
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println("子线程:"+Thread.currentThread().getName()+"执行完成");
                    //当前线程调用此方法,则计数减一
                    countDownLatch.countDown();
                }catch (Exception e){
                    e.printStackTrace();
                }
            });
        }
        // 阻塞当前线程(此例子就是main主线程), 直到计数器的值为0,主线程才开始处理
        countDownLatch.await();
        System.out.println("等待子线程执行完毕,主线程 : "+ Thread.currentThread().getName()+"开始执行,此时CountDownLatch的计数器为 :" + countDownLatch.getCount());

        //销毁线程
        exec.shutdown();
//            final int threadNum = i;
//            exec.execute(() ->{
//                try{
//                    test(threadNum);
//                }catch (Exception e){
//                    log.error("exception",e);
//                }finally {
//                    countDownLatch.countDown();
//
//                }
//            });
//
//        countDownLatch.await();
//        log.info("finish");
//        exec.shutdown();

    }

    private static void test(int threadNum) throws Exception{

        Thread.sleep(100);
        log.info("{}",threadNum);
        Thread.sleep(100);

    }
}