zoukankan      html  css  js  c++  java
  • 使用CompletableFuture实现业务服务的异步调用

    假如我有一个订单相关的统计接口,需要返回3样数据:今日订单数、今日交易额、总交易额。

    一般的我们的做法是串行调用3个函数,把调用返回的结果返回给调用者,这3次调用时串行执行的,如果每个调用耗时1秒的话,3次调用总耗时就是3秒。

    这种做法效率非常低,因为3次调用之间无所谓先后顺序,所以采用并行执行效率会更好。比如使用线程池ExecutorService实现异步调用。

    其实Java8提供了一个非常牛逼的CompletableFuture类,也可以实现异步化:

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Service;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.TimeUnit;
    
    @Slf4j
    @Service
    public class OrderService {
    
        /**
         * 今日订单数
         *
         * @return
         */
        public CompletableFuture<String> todayOrderCount() {
            return CompletableFuture.supplyAsync(() -> this.getTodayOrderCount());
        }
    
        public CompletableFuture<String> todayTurnover() {
            return CompletableFuture.supplyAsync(() -> this.getTodayTurnover());
        }
    
        public CompletableFuture<String> totalTurnover() {
            return CompletableFuture.supplyAsync(() -> this.getTotalTurnover());
        }
    
        private String getTodayOrderCount() {
            System.out.println(">>>>>>> 查询今日订单数:" + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "50";
        }
    
        /**
         * 今日交易额
         *
         * @return
         */
        private String getTodayTurnover() {
            System.out.println(">>>>>>> 查询今日交易额:" + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "200";
        }
    
        /**
         * 总交易额
         *
         * @return
         */
        private String getTotalTurnover() {
            System.out.println(">>>>>>> 查询总交易额:" + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "800";
        }
    }
    
    import com.alibaba.fastjson.JSONObject;
    import com.example.sb.service.test.impl.OrderService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.concurrent.CompletableFuture;
    
    @Slf4j
    @RestController
    @RequestMapping("/order")
    public class OrderController {
    
        @Autowired
        private OrderService orderService;
    
        @GetMapping("/report")
        public JSONObject report() {
            long start = System.currentTimeMillis();
            JSONObject json = orderReport();
            System.out.println("耗时:" + (System.currentTimeMillis() - start));
            return json;
        }
    
        private JSONObject orderReport() {
            CompletableFuture<String> todayOrderCountFuture = orderService.todayOrderCount();
            CompletableFuture<String> todayTurnoverFuture = orderService.todayTurnover();
            CompletableFuture<String> totalTurnoverFuture = orderService.totalTurnover();
    
            JSONObject json = new JSONObject();
    
            todayOrderCountFuture.whenComplete((v, t) -> {
                json.put("todayOrderCountFuture", v);
            });
            todayTurnoverFuture.whenComplete((v, t) -> {
                json.put("todayTurnoverFuture", v);
            });
            totalTurnoverFuture.whenComplete((v, t) -> {
                json.put("totalTurnoverFuture", v);
            });
    
            CompletableFuture.allOf(todayOrderCountFuture, todayTurnoverFuture, totalTurnoverFuture)
                    .thenRun(() -> System.out.println("完成!!!!"))
                    .join();
            return json;
        }
    }
    

    浏览器访问:http://localhost:8080/order/report 执行结果截图如下:

     
     

    因为每个OrderService的调用模拟都是耗时1秒,3个调用并行执行,最终耗时自然也是1秒。



    作者:不知名的蛋挞
    链接:https://www.jianshu.com/p/aa7cc1a73c72
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    NSArray和NSMutableArray的详解
    牛一网ecshop综合类模板(仿淘常州) for ecshop 2.7.3
    编写Qt Designer自定义控件(二)——编写自定义控件界面
    android关于The connection to adb is down, and a severe error has occured.这个问题的解决办法
    jboss eap6出现Tags_$$_javassist_26 cannot be cast to javassist.util.proxy.ProxyObject的解决办法
    (5)RARP:逆地址解析协议
    构成直角三角形
    共用体和枚举类型
    通过dbcc page来查看表中的数据
    ios开发-确定/自适应textView的高度
  • 原文地址:https://www.cnblogs.com/shoshana-kong/p/15196189.html
Copyright © 2011-2022 走看看