CountDownLatch
CountDownLatch是java多线程包concurrent里的一个常见工具类,通过使用它可以借助线程能力极大提升处理响应速度,且实现方式非常优雅。
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
核心api
CountDownLatch(int count) //实例化一个倒计数器,count指定计数个数 countDown() // 计数减一 await() //等待,当计数减到0时,所有线程并行执行
案例
在一个程序中需要调用两个服务的接口后才能执行下一步,那么我们需要判断这连个接口是否调用成功,并且这两个接口需要较长的时间,那么我们就可以使CountDownLatch来完成
抽象类
/** * @Description: 抽象类,统一 * @author BushRo * @date 2019-07-16 * @version 1.0 * */ public abstract class Center implements Runnable { private CountDownLatch countDown; // 计数器 private String server; // 服务名称 private boolean ok; // 服务是否调用成功标识 public Center(CountDownLatch countDown, String server) { this.countDown = countDown; this.server = server; this.ok = false; } @Override public void run() { try { work(); ok = true; } catch (Exception e) { e.printStackTrace(); ok = false; } finally { if (countDown != null) { countDown.countDown(); } } } /** * @Description: 抽象方法 * @author BushRo * @date 2019-07-16 * @version 1.0 * */ public abstract void work(); public CountDownLatch getCountDown() { return countDown; } public void setCountDown(CountDownLatch countDown) { this.countDown = countDown; } public String getServer() { return server; } public void setServer(String server) { this.server = server; } public boolean isOk() { return ok; } public void setOk(boolean ok) { this.ok = ok; } }
服务A
/** * @Description: 服务A工作 * @author BushRo * @date 2019-07-16 * @version 1.0 * */ public class ServerA extends Center { public ServerA(CountDownLatch countDown) { super(countDown, "服务A"); } @Override public void work() { System.out.println("正在获取 [" + this.getServer() + "]接口数据..."); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("获取 [" + this.getServer() + "] 数据完毕"); } }
服务B
/** * @Description: 服务B工作 * @author BushRo * @date 2019-07-16 * @version 1.0 * */ public class ServerB extends Center { public ServerB(CountDownLatch countDown) { super(countDown, "服务B"); } @Override public void work() { System.out.println("正在获取 [" + this.getServer() + "]接口数据..."); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("获取 [" + this.getServer() + "] 数据完毕"); } }
调用
在使用countDown.await();方法的时候好设置一下时间,否则有一个线程阻塞了,就会导致程序阻塞无法返回值了
public class CheckStartUp { private static List<Center> serverList; private static CountDownLatch countDown; public CheckStartUp() { } public static boolean checkAllStations() throws Exception { // 初始化2个服务 countDown = new CountDownLatch(2); // 把所有站点添加进list serverList = new ArrayList<>(); serverList.add(new ServerA(countDown)); serverList.add(new ServerB(countDown)); // 使用线程池 Executor executor = Executors.newFixedThreadPool(serverList.size()); for (Center center : serverList) { //分别执行三个线程 executor.execute(center); } // 等待线程执行完毕 //countDown.await(); /** * 在等待的时候最好设置一下时间,否则有一个线程阻塞了, * 就会导致程序阻塞无法返回值了 */ countDown.await(20,TimeUnit.SECONDS); for (Center center : serverList) { if (!center.isOk()) { return false; } } return true; } public static void main(String[] args) throws Exception { long starttime = System.currentTimeMillis(); boolean result = CheckStartUp.checkAllStations(); System.out.println("服务的调用结果为:" + result); long endtime = System.currentTimeMillis(); System.out.println("用时:" + (endtime - starttime) + "毫秒!"); } }
运行效果,这样我们就极大的节约了时间