使用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

杨泽业:WP-PostViews文章统计插接让你的文章阅读量及时更新

CompletableFuture

使用 CompletableFuture 异步组装数据

CompletableFuture使用详解

转载- CompletableFuture使用详解