场景如下:一个用户有N张不同银行卡,要求一个接口展示这N张卡的余额。如果各种银行查询余额API平均响应时间为2秒,假设用户有5张卡,就需要2*5=10秒才能展示出来结果
改造为异步处理理论上就只需要2秒,实际情况中,Completablefuture改造之后,最慢的那个API响应即为整个结果的响应时间。但用户卡数量是动态的,所以异步任务也是动态。
创建模拟查询代码
假设四大行为A、B、C、D。其中A银行API响应为2秒、B银行API响应为3秒、C银行API响应为4秒、D银行API响应为5秒。余额统一设为100
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| private static int getBankA (String cardNo) { System.out.println("查询A银行-2秒"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } return 100; }
private static int getBankB (String cardNo) { System.out.println("查询B银行-3秒"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } return 100; }
private static int getBankC (String cardNo) { System.out.println("查询C银行-4秒"); try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } return 100; }
private static int getBankD (String cardNo) { System.out.println("查询D银行-5秒"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } return 100; }
|
创建业务查询结果展示对象
1 2 3 4 5 6 7 8 9 10 11
| @Data @AllArgsConstructor public class CardInfo { private String bank; private String cardNo; private int money;
}
|
统一银行余额查询方法,路由各银行查询API封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public static CardInfo queryCardInfo(String bank, String cardNo){ int money = 0; switch (bank) { case "A" : money = getBankA(cardNo); break; case "B" : money = getBankB(cardNo); break; case "C" : money = getBankC(cardNo); break; case "D" : money = getBankD(cardNo); break; default: System.out.println("未知银行"); } return new CardInfo(bank, cardNo, money); }
|
模拟同步调用情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public static void main(String[] args) { HashMap<String, List<String>> DB = new HashMap<String, List<String>>(); DB.put("张三", Arrays.asList("1111,A", "2222,B", "3333,C", "4444,D")); DB.put("李四", Arrays.asList("11110,A", "22220,B", "33330,B", "44440,D"));
long start = System.currentTimeMillis();
List<String> cardList = DB.get("张三"); List<CardInfo> result = new ArrayList<>(); for (String info : cardList) { String[] split = info.split(","); CardInfo cardInfo = queryCardInfo(split[1], split[0]); result.add(cardInfo); } System.out.println("展示结果集:" + JSONUtil.parse(result));
long time = System.currentTimeMillis() - start; System.out.println("耗时 " + time); }
|
可以看到执行结果就是累加时间 14023 毫秒
1 2 3 4 5 6
| 查询A银行-2秒 查询B银行-3秒 查询C银行-4秒 查询D银行-5秒 展示结果集:[{"bank":"A","money":100,"cardNo":"1111"},{"bank":"B","money":100,"cardNo":"2222"},{"bank":"C","money":100,"cardNo":"3333"},{"bank":"D","money":100,"cardNo":"4444"}] 耗时 14023
|
改造为使用Completablefuture
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public static void main(String[] args) { HashMap<String, List<String>> DB = new HashMap<String, List<String>>(); DB.put("张三", Arrays.asList("1111,A", "2222,B", "3333,C", "4444,D")); DB.put("李四", Arrays.asList("11110,A", "22220,B", "33330,B", "44440,D"));
long start = System.currentTimeMillis();
List<String> cardList = DB.get("张三"); List<CardInfo> result = new ArrayList<>(); ExecutorService threadPool = Executors.newFixedThreadPool(5); List<CompletableFuture<CardInfo>> futureList = cardList.stream().map(info -> { String[] split = info.split(","); return CompletableFuture.supplyAsync(() -> queryCardInfo(split[1], split[0]), threadPool); }).collect(Collectors.toList());
CompletableFuture allFuture = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));
allFuture.thenAccept(o -> futureList.forEach(job -> { try { result.add(job.get()); } catch (Exception e) { e.printStackTrace(); } }) ); allFuture.join(); System.out.println("展示结果集:" + JSONUtil.parse(result));
long time = System.currentTimeMillis() - start; System.out.println("耗时 " + time); }
|
可以看到执行结果就是最慢的D银行的时间 5059毫秒。说明任务是同步进行的,结果集依赖所有任务执行完成,所以响应时间就是最慢的D银行API 5秒
1 2 3 4 5 6
| 查询A银行-2秒 查询B银行-3秒 查询C银行-4秒 查询D银行-5秒 展示结果集:[{"bank":"A","money":100,"cardNo":"1111"},{"bank":"B","money":100,"cardNo":"2222"},{"bank":"C","money":100,"cardNo":"3333"},{"bank":"D","money":100,"cardNo":"4444"}] 耗时 5059
|
OK,上面就是一个简单的Completablefuture使用Demo实践。下一篇再出一个Completablefuture使用原理
关于Completablefuture的文章,建议大家去看下 美团的技术博客