zoukankan      html  css  js  c++  java
  • 使用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秒。

  • 相关阅读:
    ES head安装笔记, 还没有试
    sed用法笔记
    Kibana笔记
    ElasticSearch笔记
    Mongo聚合笔记
    java 判断是否为数字
    Redis 一:安装篇
    make问题:make[1] entering directory
    Java 多线程 简单实例 (消费者与生成者)的关系
    Java 多线程 简单实例 (Runnable)
  • 原文地址:https://www.cnblogs.com/jun1019/p/11521145.html
Copyright © 2011-2022 走看看