likes
comments
collection
share

线程并发工具类(二):CountDownLatch

作者站长头像
站长
· 阅读数 6

线程并发中的工具类:CountDownLatch

  • CountDownLatch:闭锁

    • 概述:

      • 一个或多个线程等待其他的线程完成工作后,再执行

      • 应用场景:比如启动一个框架中,将数据初始化放到单独的一个/多个线程,主线程等这些线程执行完后,在执行(将初始化工作放在主线程中会影响性能)

      • 内在机制:

        • 工作线程调用,里面的await(),等待"初始化"线程执行完成;
        • 里面有一个计数器(CNT,一般是有初值的),一旦某个"初始化"线程完成(或完成一部分),那么就调用countDown()将CNT减去1,
        • 当CNT为0的时候,工作线程继续执行
      • 执行流程:

        线程并发工具类(二):CountDownLatch

      • 执行细节:

        • CNT与初始化线程是没有什么关系的,一个线程完全可以多扣几次

        • 初始化线程在CNT为0的时候,这个线程完全可以继续执行

          • 直接搞一个线程池,干完初始化又去干其他的事情
        • 等待的线程可以有多个

        • 一定要注意,CNT的设置,如果说没有扣完--->业务线程被阻塞掉了

    • 代码实现:

       package cn.enjoyedu.ch2.tools;
       ​
       import java.util.concurrent.CountDownLatch;
       ​
       import cn.enjoyedu.tools.SleepTools;
       ​
       /**
        *类说明:演示CountDownLatch用法,
        * 共5个初始化子线程,6个闭锁扣除点,扣除完毕后,主线程和业务线程才能继续执行
        */
       public class UseCountDownLatch {
           
           //TODO
           //六个闭锁点
           static CountDownLatch latch = new CountDownLatch(6);
           //模拟初始化线程
           private static class InitThread implements Runnable{
       ​
               @Override
               public void run() {
                   System.out.println("Thread_"+Thread.currentThread().getId()
                           +" ready init work......");
                   //当初始化线程完成一个初始化操作后CNT减一;实际上可以随便减,减到0,就意味着初始化工作结束了
                   latch.countDown();
       ​
                   for(int i =0;i<2;i++) {
                       System.out.println("Thread_"+Thread.currentThread().getId()
                               +" ........continue do its work");
                   }
               }
           }
       ​
           //业务线程:等待latch的CNT清零
           private static class BusiThread implements Runnable{
       ​
               @Override
               public void run() {
                   //这里业务线程就被唤醒了,意味着初始化工作结束,
                   try {
                       latch.await();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   for(int i =0;i<3;i++) {
                       System.out.println("BusiThread_"+Thread.currentThread().getId()
                               +" do business-----");
                   }
               }
           }
       ​
           public static void main(String[] args) throws InterruptedException {
               new Thread(new Runnable() {
                   @Override
                   public void run() {
                       SleepTools.ms(1);
                       System.out.println("Thread_"+Thread.currentThread().getId()
                               +" ready init work step 1st......");
                       //模拟在一个线程中可以对CNT进行二次扣减
                       //第一次扣减
                       latch.countDown();
                       System.out.println("begin step 2nd.......");
                       SleepTools.ms(1);
                       System.out.println("Thread_"+Thread.currentThread().getId()
                               +" ready init work step 2nd......");
                       //第二次扣减
                       latch.countDown();
                   }
               }).start();
               new Thread(new BusiThread()).start();
               for(int i=0;i<=3;i++){
                   Thread thread = new Thread(new InitThread());
                   thread.start();
               }
       ​
               //可以让主线程也等待,意味着等待的线程可以有多个
               latch.await();
               System.out.println("Main do ites work........");
           }
       }
      
    • 运行截图:

      线程并发工具类(二):CountDownLatch