zoukankan      html  css  js  c++  java
  • CountDownLatch学习

    参考原文

    1. 什么时候使用CountDownLatch

    CountDownLatch是什么

    CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。
    单词Latch的中文翻译是门闩,也就是有“门锁”的功能,所以当门没有打开时,N个人是不能进入屋内的,也就是N个线程是不能继续往下运行的,支持这样的特性可以控制线程执行任务的时机

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

    CountDownLatch 常用API

    构造方法:

    public CountDown(int count){} 
    //count初始化计数值,一旦count初始化完成后,就不可重新初始化或者修改CountDownLatch对象的内部计数器的值。 
    

    常用方法:

    public void await() {}; //使当前线程挂起,直到计数值为0时,才继续往下执行。
    public boolean await(long timeout , TimeUnit timeUnit) throws InterruptExcetion {};
    public void  countDown() {} //将count值减1
    

    应用场景

    CountDownLatch的一个非常典型的应用场景就是:有一个任务想要往下执行,但必须等到其他多个任务执行(如果是单个任务 顺序执行就好了)完毕后才进行继续往下执行。此时,我们可以在这个等待其他任务的线程里调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。

    
    import java.util.Arrays;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.Executor;
    import java.util.concurrent.Executors;
    
    /**
     * 模拟程序启动时 相关环境检查
     */
    public class CountDownLatchTest {
        public static void main(String[] args) {
            try {
                Boolean result = ApplicationStartupUtil.checkExtenalServoce();
                if(result) {
                    System.out.println("健康检查全部健康");
                } else {
                    throw new RuntimeException("程序依赖环境不健康");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    abstract class BaseHealthChecker implements Runnable {
    
        private CountDownLatch countDownLatch ;
    
        protected boolean isHealth ;
    
        private String serviceName ;
    
        public BaseHealthChecker(String serviceName , CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
            this.serviceName = serviceName ;
            isHealth = false ;
        }
    
        @Override
        public void run() {
            try {
                this.verifyService();
                isHealth = true ;
            }catch (Exception e) {
                e.printStackTrace();
                isHealth = false ;
            } finally {
                if(countDownLatch != null) {
                    countDownLatch.countDown();
                }
            }
        }
    
        abstract void verifyService() ;
    
        public boolean isHealth() {
            return isHealth;
        }
    
        public String getServiceName() {
            return serviceName;
        }
    }
    
    
    class NetWorkHealthChecker extends BaseHealthChecker {
    
        public NetWorkHealthChecker( CountDownLatch countDownLatch) {
            super( "NetWorkHealthChecker" , countDownLatch ) ;
        }
    
        @Override
        void verifyService() {
            System.out.println("starting Checking " + this.getServiceName());
    
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println( this.getServiceName() + " is Health");
            isHealth = true ;
        }
    }
    
    class DatabaseHealthChecker extends BaseHealthChecker {
    
        public DatabaseHealthChecker( CountDownLatch countDownLatch) {
            super( "DatabaseHealthChecker" , countDownLatch ) ;
        }
    
        @Override
        void verifyService() {
    
            System.out.println("starting Checking " + this.getServiceName());
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println( this.getServiceName() + " is Health");
            isHealth = true ;
        }
    }
    
    class ApplicationStartupUtil {
    
        private static List<BaseHealthChecker> healthCheckerList ;
    
        private static CountDownLatch countDownLatch ;
    
        private ApplicationStartupUtil() {
    
        }
    
        public static boolean checkExtenalServoce() throws Exception {
    
            countDownLatch = new CountDownLatch(2) ;
            healthCheckerList = Arrays.asList(new DatabaseHealthChecker(countDownLatch) , new NetWorkHealthChecker(countDownLatch)) ;
    
            Executor executor = Executors.newFixedThreadPool(healthCheckerList.size()) ;
    
            healthCheckerList.forEach((num)-> executor.execute(num));
    
            countDownLatch.await() ;
            System.out.println(countDownLatch.getCount());
    
            //等待健康检查完毕
            healthCheckerList.forEach((num) -> {
                System.out.println(num.isHealth);
                if(!num.isHealth()) {
                    throw new RuntimeException(num.getServiceName() + "健康检查失败");
                }
            });
    
            return true ;
    
        }
    }
    
  • 相关阅读:
    react路由组件&&非路由组件
    react函数式组件(非路由组件)实现路由跳转
    react使用antd组件递归实现左侧菜单导航树
    【LeetCode】65. Valid Number
    【LeetCode】66. Plus One (2 solutions)
    【LeetCode】68. Text Justification
    【LeetCode】69. Sqrt(x) (2 solutions)
    【LeetCode】72. Edit Distance
    【LeetCode】73. Set Matrix Zeroes (2 solutions)
    【LeetCode】76. Minimum Window Substring
  • 原文地址:https://www.cnblogs.com/boothsun/p/7168510.html
Copyright © 2011-2022 走看看