使用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秒。
使用CompletableFuture实现业务服务的异步调用实战代码的更多相关文章
- ArcGIS Runtime SDK for Android开发之调用GP服务(异步调用)
一.背景说明 通过调用GP服务,Android客户端也能实现专业的.复杂的GIS分析处理功能,从而增加应用的实用价值. ArcGIS Server发布的GP服务,分为同步和异步两种类型,一般执行步骤较 ...
- 通讯服务类API调用的代码示例合集:短信服务、手机号归属地查询、电信基站查询等
以下示例代码适用于 www.apishop.net 网站下的API,使用本文提及的接口调用代码示例前,您需要先申请相应的API服务. 短信服务:通知类和验证码短信,全国三网合一通道,5秒内到达,费用低 ...
- 出行服务类API调用的代码示例合集:长途汽车查询、车型大全、火车票查询等
以下示例代码适用于 www.apishop.net 网站下的API,使用本文提及的接口调用代码示例前,您需要先申请相应的API服务. 长途汽车查询:全国主要城市的长途汽车时刻查询,汽车站查询 车型大全 ...
- Dubbo中CompletableFuture异步调用
使用Future实现异步调用,对于无需获取返回值的操作来说不存在问题,但消费者若需要获取到最终的异步执行结果,则会出现问题:消费者在使用Future的get()方法获取返回值时被阻塞.为了解决这个问题 ...
- WCF初探-11:WCF客户端异步调用服务
前言: 在上一篇WCF初探-10:WCF客户端调用服务 中,我详细介绍了WCF客户端调用服务的方法,但是,这些操作都是同步进行的.有时我们需要长时间处理应用程序并得到返回结果,但又不想影响程序后面代码 ...
- mvc路由引起异步调用web服务的问题
从一篇blog得知使用脚本可以异步调用Web服务,觉得很新鲜,因为自己很少用到Web服务,所以决定写一写看看什么效果. 首先在UI项目(我使用的是MVC4.0)里创建一个Web服务. 添加Web服务后 ...
- 使用 ajax 异步调用数据
ajax 脚本 <script type="text/javascript" > function show(page) { var xmlhttp; try { xm ...
- 006-优化web请求二-应用缓存、异步调用【Future、ListenableFuture、CompletableFuture】、ETag、WebSocket【SockJS、Stomp】
四.应用缓存 使用spring应用缓存.使用方式:使用@EnableCache注解激活Spring的缓存功能,需要创建一个CacheManager来处理缓存.如使用一个内存缓存示例 package c ...
- 多线程编程学习笔记——异步调用WCF服务
接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...
随机推荐
- Linux系统禁止root账号远程登录
修改配置文件/etc/ssh/sshd_config,去掉PermitRootLogin前的注释,修改值为no,然后重启sshd服务即可 #LoginGraceTime 2m PermitRootLo ...
- prometheus学习系列四: Prometheus详述
数据模型 Prometheus 是将所有数据存为时序数据. 每个时序数据是由指标名称和可选的键值对(称之为标签)唯一标识. 度量类型 counter: 单调递增的计数器,如果标识已经服务的请求数量可以 ...
- excel 大文件解析原理实现
问题 目前的excel 不像之前的excel了可以支持的数据量更大,可以支持支持1048576行,16384列. 之前使用poi读取,直接报错,使用excel 事件的方式读取,还有不少的bug,关键是 ...
- backtrace() returns only one stack frame
参考: 在Linux中如何利用backtrace信息解决程序崩溃的问题 linux 打印堆栈方法 https://devtalk.nvidia.com/default/topic/987279/jet ...
- httprunner学习20-跳过用例skip/skipIf/skipUnless
前言 在实际工作中,我们有时候会需要对测试用例加判断,比如某个接口功能暂时去掉了,我们希望对这个用例skip不去执行. 当其它的接口依赖于登陆接口返回的token时候,如果登陆都失败了,后面的接口,我 ...
- 项目Beta冲刺--6/7
项目Beta冲刺--6/7 作业要求 这个作业属于哪个课程 软件工程1916-W(福州大学) 这个作业要求在哪里 项目Beta冲刺 团队名称 基于云的胜利冲锋队 项目名称 云评:高校学生成绩综合评估及 ...
- Python基础知识笔记-作用域
Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的. 变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称.Python的作用域一共有4种,分别是: ...
- Spring Boot属性配置文件:application.properties 详解
学习资料 网址 官方说明文档 https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-pro ...
- MySQL中Count函数的参数该传入什么样的值?
MySQL中Count函数的参数该传入什么样的值? 查询用户表中总记录 用户表中信息如下: 1.SELECT COUNT(*) FROM USER 结果为:3条 2. SELECT COUNT(us ...
- springboot集成mail实现邮件服务
1,新建mailconfig类,对邮件服务固定配置进行实体封装: import java.util.Properties; import org.springframework.beans.facto ...