java-线程池异步获取多平台接口返回结果
业务场景:
公司需要集成多个系统的待办任务数据,将其整合在我们常用的OA系统上展示,这样就不用登录每个系统去查看自己每天的待办任务有哪些。
原有思路:
按照同步的方式,逐一调取每个系统提供的待办接口,获取结果,最后整合汇总。
出现的问题:
随着对接系统的增加,网页刷新出内容的速度会越来越慢,甚至接口超时。
解决方案:
使用线程池,多线程同时调用各系统接口。
代码如下:
System1.java
public class System1 implements Callable<List<Result>> { String params1 = ""; String url1 = ""; public System1(String params1, String url1) { // 通过构造函数,传入不同的请求参数和请求地址 this.params1 = params1; this.url1 = url1; } @Override public List<Result> call() throws Exception { System.out.println("begin-----" + Thread.currentThread().getName() + "-----" + new Date() + " system1()"); List<Result> res = new ArrayList<>(); /** * 这里可以写调取各系统接口,并获取返回结果,封装至res内的逻辑 */ Thread.sleep(5000); // 为体现出异步效果,加入延时5s的逻辑;实际业务中删除即可 System.out.println("end-----" + Thread.currentThread().getName() + "-----" + new Date() + " system1()"); return res; } }
System2.java
public class System2 implements Callable<List<Result>> { String params2 = ""; String url2 = ""; public System2(String params2, String url2) { this.params2 = params2; this.url2 = url2; } @Override public List<Result> call() throws Exception { System.out.println("begin-----" + Thread.currentThread().getName() + "-----" + new Date() + " system2()"); List<Result> res = new ArrayList<>(); /** * 调取其他系统接口,并获取返回结果,封装至res内的逻辑 */ Thread.sleep(5000); // 为体现出异步效果,加入延时5s的逻辑;实际业务中删除即可 System.out.println("end-----" + Thread.currentThread().getName() + "-----" + new Date() + " system2()"); return res; } }
SystemAll.java
public class SystemAll { public List<Result> getAllResult() { LocalDateTime beginTime = LocalDateTime.now(); // 配置线程池:核心线程数量:5;最大线程数:10;空余线程存活时长:1s;存储等待执行任务的队列长度:100;任务拒绝策略:CallerRunsPolicy ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.CallerRunsPolicy()); List<Callable<List<Result>>> callableList = new ArrayList<>(); // 线程列表 List<Future<List<Result>>> futureList = new ArrayList<>(); // 线程返回结果列表 List<Result> res = new ArrayList<>(); // 汇总结果 callableList.add(new System1("params1", "url1")); // 单个线程执行类:调取system1系统接口 callableList.add(new System2("params2", "url2")); for (Callable<List<Result>> callableItem : callableList) { Future<List<Result>> submitRes = executor.submit(callableItem); // 提交单个线程至线程池 futureList.add(submitRes); // res.addAll(submitRes.get()); // 不要在此处通过submitRes.get()方法获取结果,会导致线程等待,非异步执行 } for (Future<List<Result>> futureItem : futureList) { List<Result> resultItem = new ArrayList<>(); try { resultItem = futureItem.get(); // 获取各个线程的返回结果 } catch (Exception e) { executor.shutdown(); e.printStackTrace(); } res.addAll(resultItem); } executor.shutdown(); // 关闭线程池,不再接受新任务;但队列里的任务会执行完毕 while (executor.isTerminated()) { // 调用shutdown()后,所有提交的任务完成后,返回true; System.out.println(res); System.out.println(res.size()); break; } // while (!executor.isTerminated()) {} // 更简洁的写法 Long timeConsuming = Duration.between(beginTime, LocalDateTime.now()).toMillis(); System.out.println("时间消耗:" + timeConsuming); return res; } public static void main(String[] args) { new SystemAll().getAllResult(); } }
运行打印结果:
可以看出:两个系统均需要耗时5s得到返回结果,因开启多线程执行,最终总耗时也只是5s;随着对接系统的增加,异步实现的效率提升效果更加明显。