假如我有一个订单相关的统计接口,需要返回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秒。

使用CompletableFuture实现业务服务的异步调用实战代码的更多相关文章

  1. ArcGIS Runtime SDK for Android开发之调用GP服务(异步调用)

    一.背景说明 通过调用GP服务,Android客户端也能实现专业的.复杂的GIS分析处理功能,从而增加应用的实用价值. ArcGIS Server发布的GP服务,分为同步和异步两种类型,一般执行步骤较 ...

  2. 通讯服务类API调用的代码示例合集:短信服务、手机号归属地查询、电信基站查询等

    以下示例代码适用于 www.apishop.net 网站下的API,使用本文提及的接口调用代码示例前,您需要先申请相应的API服务. 短信服务:通知类和验证码短信,全国三网合一通道,5秒内到达,费用低 ...

  3. 出行服务类API调用的代码示例合集:长途汽车查询、车型大全、火车票查询等

    以下示例代码适用于 www.apishop.net 网站下的API,使用本文提及的接口调用代码示例前,您需要先申请相应的API服务. 长途汽车查询:全国主要城市的长途汽车时刻查询,汽车站查询 车型大全 ...

  4. Dubbo中CompletableFuture异步调用

    使用Future实现异步调用,对于无需获取返回值的操作来说不存在问题,但消费者若需要获取到最终的异步执行结果,则会出现问题:消费者在使用Future的get()方法获取返回值时被阻塞.为了解决这个问题 ...

  5. WCF初探-11:WCF客户端异步调用服务

    前言: 在上一篇WCF初探-10:WCF客户端调用服务 中,我详细介绍了WCF客户端调用服务的方法,但是,这些操作都是同步进行的.有时我们需要长时间处理应用程序并得到返回结果,但又不想影响程序后面代码 ...

  6. mvc路由引起异步调用web服务的问题

    从一篇blog得知使用脚本可以异步调用Web服务,觉得很新鲜,因为自己很少用到Web服务,所以决定写一写看看什么效果. 首先在UI项目(我使用的是MVC4.0)里创建一个Web服务. 添加Web服务后 ...

  7. 使用 ajax 异步调用数据

    ajax 脚本 <script type="text/javascript" > function show(page) { var xmlhttp; try { xm ...

  8. 006-优化web请求二-应用缓存、异步调用【Future、ListenableFuture、CompletableFuture】、ETag、WebSocket【SockJS、Stomp】

    四.应用缓存 使用spring应用缓存.使用方式:使用@EnableCache注解激活Spring的缓存功能,需要创建一个CacheManager来处理缓存.如使用一个内存缓存示例 package c ...

  9. 多线程编程学习笔记——异步调用WCF服务

    接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...

随机推荐

  1. linux下apache和tomcat整合

    一 Apache与Tomcat比较联系 apache支持静态页,tomcat支持动态的,比如servlet等. 一般使用apache+tomcat的话,apache只是作为一个转发,对jsp的处理是由 ...

  2. Odoo权限控制详解

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826105.html 一:Odoo中的权限设置主要有以下5种 1)菜单.报表的访问权限 Odoo可以设置菜 ...

  3. 详解php概念以及主配置文件

    浏览器仅能够解码HTML格式的文档,对于非HTML格式的文档,浏览器调用插件或者通过CGI接口调用其他程序来解码. 动态网站: 我们在服务器端或客户端执行了一段脚本或者一段程序,这段程序执行的结果根据 ...

  4. C语言scanf函数转换说明表及其修饰符表

    1. 对于上一篇文章,总结printf()输出,C库也包含了多个输入函数, scanf()是最常用的一个,也是经常与printf()经常一起搭配使用的函数之一. scanf()和printf()类似, ...

  5. 洛谷P4180 【模板】严格次小生成树[BJWC2010] 题解

    虽然中途写的时候有点波折,但是最后一发A,还是有点爽. 这虽然是个模板题,但还是涉及到许多知识的= = 首先我们求出一个最小生成树,并且求出其边权和\(ans\).那么现在考虑加入其它的边,每次加入在 ...

  6. 【比赛游记】NOI2019打铁记

    上接 NOIWC2019冬眠记.(THUPC,CTS,APIO)2019四连爆蛋记 和 THUSC2019酱油记. Day0.5 笔试 AK 是容易的. 国家队选手见面会太好玩了啊! Day1 Day ...

  7. MySQL 多行数据合并 GROUP_CONCAT

    表结构及数据 DROP TABLE IF EXISTS `course`;CREATE TABLE `course` ( `name` varchar(255) CHARACTER SET utf8 ...

  8. Linux:使用awk命令获取文本的某一行,某一列;sed插入指定的内容到指定文件中

    awk相关用法: 1.打印文件的第一列(域)                 : awk '{print $1}' filename2.打印文件的前两列(域)                 : aw ...

  9. react hooks沉思录

    将UI组件抽象为状态处理机.分为普通状态和副作用状态. 一.综述 useState:处理函数只改变引用的状态本身:副作用状态:会对引用状态以外的状态和变量进行修改:useReducer:用解藕化的机制 ...

  10. SpringBoot整合ActiveMQ发送邮件

    虽然ActiveMQ以被其他MQ所替代,但仍有学习的意义,本文采用邮件发送的例子展示ActiveMQ 1. 生产者1.1 引入maven依赖1.2 application.yml配置1.3 创建配置类 ...