使用CompletableFuture让你的多个业务调用并行执行
Posted jun1019
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用CompletableFuture让你的多个业务调用并行执行相关的知识,希望对你有一定的参考价值。
假如我有一个订单相关的统计接口,需要返回3样数据:今日订单数、今日交易额、总交易额。
一般的我们的做法是串行调用3个函数,把调用返回的结果返回给调用者,这3次调用时串行执行的,如果每个调用耗时1秒的话,3次调用总耗时就是3秒。
这种做法效率非常低,因为3次调用之间无所谓先后顺序,所以采用并行执行效率会更好。比如使用线程池ExecutorService实现异步调用。
其实Java8提供了一个非常牛逼的CompletableFuture类,也可以实现异步化:
1 import lombok.extern.slf4j.Slf4j; 2 import org.springframework.stereotype.Service; 3 4 import java.util.concurrent.CompletableFuture; 5 import java.util.concurrent.TimeUnit; 6 7 @Slf4j 8 @Service 9 public class OrderService 10 11 /** 12 * 今日订单数 13 * 14 * @return 15 */ 16 public CompletableFuture<String> todayOrderCount() 17 return CompletableFuture.supplyAsync(() -> this.getTodayOrderCount()); 18 19 20 public CompletableFuture<String> todayTurnover() 21 return CompletableFuture.supplyAsync(() -> this.getTodayTurnover()); 22 23 24 public CompletableFuture<String> totalTurnover() 25 return CompletableFuture.supplyAsync(() -> this.getTotalTurnover()); 26 27 28 private String getTodayOrderCount() 29 System.out.println(">>>>>>> 查询今日订单数:" + Thread.currentThread().getName()); 30 try 31 TimeUnit.SECONDS.sleep(1); 32 catch (InterruptedException e) 33 e.printStackTrace(); 34 35 return "50"; 36 37 38 /** 39 * 今日交易额 40 * 41 * @return 42 */ 43 private String getTodayTurnover() 44 System.out.println(">>>>>>> 查询今日交易额:" + Thread.currentThread().getName()); 45 try 46 TimeUnit.SECONDS.sleep(1); 47 catch (InterruptedException e) 48 e.printStackTrace(); 49 50 return "200"; 51 52 53 /** 54 * 总交易额 55 * 56 * @return 57 */ 58 private String getTotalTurnover() 59 System.out.println(">>>>>>> 查询总交易额:" + Thread.currentThread().getName()); 60 try 61 TimeUnit.SECONDS.sleep(1); 62 catch (InterruptedException e) 63 e.printStackTrace(); 64 65 return "800"; 66 67
1 import com.alibaba.fastjson.JSONObject; 2 import com.example.sb.service.test.impl.OrderService; 3 import lombok.extern.slf4j.Slf4j; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.web.bind.annotation.GetMapping; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 import org.springframework.web.bind.annotation.RestController; 8 9 import java.util.concurrent.CompletableFuture; 10 11 @Slf4j 12 @RestController 13 @RequestMapping("/order") 14 public class OrderController 15 16 @Autowired 17 private OrderService orderService; 18 19 @GetMapping("/report") 20 public JSONObject report() 21 long start = System.currentTimeMillis(); 22 JSONObject json = orderReport(); 23 System.out.println("耗时:" + (System.currentTimeMillis() - start)); 24 return json; 25 26 27 private JSONObject orderReport() 28 CompletableFuture<String> todayOrderCountFuture = orderService.todayOrderCount(); 29 CompletableFuture<String> todayTurnoverFuture = orderService.todayTurnover(); 30 CompletableFuture<String> totalTurnoverFuture = orderService.totalTurnover(); 31 32 JSONObject json = new JSONObject(); 33 34 todayOrderCountFuture.whenComplete((v, t) -> 35 json.put("todayOrderCountFuture", v); 36 ); 37 todayTurnoverFuture.whenComplete((v, t) -> 38 json.put("todayTurnoverFuture", v); 39 ); 40 totalTurnoverFuture.whenComplete((v, t) -> 41 json.put("totalTurnoverFuture", v); 42 ); 43 44 CompletableFuture.allOf(todayOrderCountFuture, todayTurnoverFuture, totalTurnoverFuture) 45 .thenRun(() -> System.out.println("完成!!!!")) 46 .join(); 47 return json; 48 49
浏览器访问:http://localhost:8080/order/report 执行结果截图如下:
因为每个OrderService的调用模拟都是耗时1秒,3个调用并行执行,最终耗时自然也是1秒。
以上是关于使用CompletableFuture让你的多个业务调用并行执行的主要内容,如果未能解决你的问题,请参考以下文章
JUC-Java多线程Future,CompletableFuture