• 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 ;
    
        }
    }
    
  • 相关阅读:
    LayoutInflater(布局服务)
    FOTA升级
    APK安装过程及原理详解
    Context类型
    Android应用的persistent属性
    Notification(状态栏通知)详解
    Handler消息传递机制浅析
    Selenium HTMLTestRunner 无法生成测试报告的总结
    【python】远程使用rsa登录sftp,上传下载文件
    02.性能测试中的指标
  • 原文地址:https://www.cnblogs.com/boothsun/p/7168510.html
Copyright © 2020-2023  润新知