使用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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM