看了几篇博客,说用CountDownLatch实现一个先执行完子线程,再执行主线程的例子。因此写一篇博客总结一下。
一、CountDownLatch了解
1.CountDownLatch继承了AbstractQueuedSynchronizer类,很多方法都封装了在这个类里面,感兴趣可以看一下。内部写了一个Sync类,对其进行各种操作,以完成各个功能。
2.其原理是实现了一个计数器,通过对计数器操作,来实现对各个子线程的监控
二、例子
1.在启动服务前,需要对各个组件进行健康检查,因此设计一个方案,对各个组件进行检查,环境都ok后,再执行主线程。
2.先定义一个抽象类,该类实现了Runnable,用来进行健康检查
1 public abstract class BaseHealthChecker implements Runnable { 2 //Counter 3 private CountDownLatch counter; 4 private String serviceName; 5 private boolean isServiceOk; 6 7 public abstract void checkHealth(); 8 9 public String getServiceName() { 10 return serviceName; 11 } 12 13 public boolean isServiceOk() { 14 return isServiceOk; 15 } 16 17 public BaseHealthChecker(String serviceName, CountDownLatch countDownLatch) { 18 this.counter = countDownLatch; 19 this.serviceName = serviceName; 20 this.isServiceOk = false; 21 } 22 23 @Override 24 public void run() { 25 try { 26 checkHealth(); 27 isServiceOk = true; 28 } catch (Throwable t) { 29 t.printStackTrace(); 30 isServiceOk = false; 31 } finally { 32 //Always count down counter 33 if (counter != null) { 34 counter.countDown(); 35 } 36 } 37 } 38 }
3.再定义一个HealthChecker.
1 package countdownlatch; 2 3 import java.util.concurrent.CountDownLatch; 4 5 /** 6 * Created by adrian.wu on 2018/12/18. 7 */ 8 public class HealthChecker extends BaseHealthChecker{ 9 public HealthChecker(String serviceName, CountDownLatch counter){ 10 super(serviceName, counter); 11 } 12 13 @Override 14 public void checkHealth(){ 15 System.out.println("Check " + this.getServiceName()); 16 try { 17 Thread.sleep(7000); 18 }catch (InterruptedException e){ 19 e.printStackTrace(); 20 } 21 System.out.println(this.getServiceName() + " is Ok"); 22 } 23 }
4.设定要检查哪些service
1 package countdownlatch; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import java.util.concurrent.CountDownLatch; 6 import java.util.concurrent.Executor; 7 import java.util.concurrent.Executors; 8 9 /** 10 * Created by adrian.wu on 2018/12/18. 11 */ 12 public class ApplicationStartupUtil { 13 private static List<BaseHealthChecker> services; 14 15 private static CountDownLatch latch; 16 17 private ApplicationStartupUtil() { 18 } 19 20 private final static ApplicationStartupUtil INSTANCE = new ApplicationStartupUtil(); 21 22 public static ApplicationStartupUtil getInstance() { 23 return INSTANCE; 24 } 25 26 public static boolean checkExternalServices() throws Exception { 27 //Initialize the service checkers 28 latch = new CountDownLatch(4); 29 30 services = new ArrayList<>(); 31 32 services.add(new HealthChecker("Flink Cluster", latch)); 33 34 services.add(new HealthChecker("Hbase Cluster", latch)); 35 36 services.add(new HealthChecker("Spark Cluster", latch)); 37 38 services.add(new HealthChecker("Kafka Cluster", latch)); 39 40 Executor executor = Executors.newFixedThreadPool(services.size()); 41 42 for (final BaseHealthChecker v : services) { 43 executor.execute(v); 44 } 45 46 //wait all threads okay 47 latch.await(); 48 49 for (final BaseHealthChecker v : services) { 50 if (!v.isServiceOk()) { 51 return false; 52 } 53 } 54 55 return true; 56 } 57 }
5.检查服务
1 package countdownlatch; 2 3 /** 4 * Created by adrian.wu on 2018/12/18. 5 */ 6 public class Check { 7 public static void main(String[] args) { 8 boolean result = false; 9 try { 10 result = ApplicationStartupUtil.checkExternalServices(); 11 } catch (Exception e) { 12 e.printStackTrace(); 13 } 14 System.out.println("Services check is ok. Result: " + result); 15 } 16 }
参考:http://www.importnew.com/15731.html