当前位置: 首页 > news >正文

异步调用实践:Async,Future, TaskExecutor、EventListener

1. 异步调用概述

异步调用允许一个方法调用在不被当前线程阻塞的情况下继续执行,而调用者可以继续执行其他任务,直到异步操作完成。

在Spring Boot中,异步调用常用于提高应用的响应性和吞吐量,尤其是在处理长时间运行的任务时,如文件处理、数据库查询、网络请求等。

2. 异步调用注意点

  • 线程安全性:确保异步方法中访问的共享资源是线程安全的。
  • 异常处理:异步方法中的异常需要被捕获并适当处理,或者通过某种机制返回给调用者。
  • 返回类型:异步方法的返回类型通常是voidFuture<T>CompletableFuture<T>,以便调用者可以检查异步操作的结果或状态。
  • 配置异步执行器:根据需要配置线程池大小等参数,以避免资源耗尽。
  • 避免在相同类的方法中调用异步方法:因为这将绕过Spring的代理机制,导致异步调用不生效。

3. 异步调用场景

假设我们有一个在线书店应用,用户下单后需要发送订单确认邮件和更新库存。

这两个操作都是耗时的,我们希望它们异步执行,以便用户能够立即得到订单提交的反馈。

4. 具体实现

(1)@Async

首先,需要在Spring Boot中启用异步支持,在启动类上添加@EnableAsync注解。然后,在需要异步执行的方法上添加@Async注解。

@SpringBootApplication
@EnableAsync
public class BookstoreApplication {public static void main(String[] args) {SpringApplication.run(BookstoreApplication.class, args);}
}@Service
public class OrderService {@Asyncpublic void processOrder(Order order) {// 模拟发送邮件sendOrderConfirmationEmail(order);// 模拟更新库存updateStock(order);}// 实现sendOrderConfirmationEmail和updateStock方法
}

(2)CompletableFuture

CompletableFuture提供了更灵活的异步编程模型,允许你编写非阻塞代码,同时以声明方式处理异步完成时的结果。

@Service
public class OrderService {public CompletableFuture<Void> processOrderAsync(Order order) {CompletableFuture<Void> emailFuture = CompletableFuture.runAsync(() -> sendOrderConfirmationEmail(order));CompletableFuture<Void> stockFuture = CompletableFuture.runAsync(() -> updateStock(order));return CompletableFuture.allOf(emailFuture, stockFuture).thenApply(v -> null);}// 实现sendOrderConfirmationEmail和updateStock方法
}

(3)TaskExecutor

TaskExecutor是Spring提供的用于执行异步任务的接口。你可以通过配置一个TaskExecutor来管理线程池。

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(25);executor.initialize();return executor;}}@Service
public class OrderService {@Autowiredprivate TaskExecutor taskExecutor;public void processOrder(Order order) {taskExecutor.execute(() -> sendOrderConfirmationEmail(order));taskExecutor.execute(() -> updateStock(order));}// 实现sendOrderConfirmationEmail和updateStock方法
}

(4)@EventListener

虽然@EventListener主要用于事件监听,但你可以结合异步任务来监听特定事件(如订单创建事件),并异步处理。

@Component
public class OrderEventListener {@Async@EventListenerpublic void handleOrderCreatedEvent(OrderCreatedEvent event) {Order order = event.getOrder();sendOrderConfirmationEmail(order);updateStock(order);}// 实现sendOrderConfirmationEmail和updateStock方法
}// 假设你有一个OrderCreatedEvent类
public class OrderCreatedEvent extends ApplicationEvent {private Order order;public OrderCreatedEvent(Object source, Order order) {super(source);this.order = order;}// getter和setter
}

5. 总结

在Spring Boot中,实现异步调用可以通过多种方式,包括@Async注解、CompletableFuture、自定义TaskExecutor以及结合@EventListener进行异步事件处理。

每种方式都有其适用场景和优缺点,开发者应根据实际需求选择最合适的方法。

同时,使用异步调用时需要注意线程安全、异常处理以及合理配置异步。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 网络编程----TCP/IP协议
  • scrcpy源码 windows10编译傻瓜式教程
  • 字符串查找 - 模拟实现strstr 、BF算法 、 KMP算法
  • 【AI】算力底座的巨变
  • golang中的星号*通配符字符串模式匹配 和问号? 通配符字符串模式匹配的2种实现方法 和相关的单元测试用例
  • SQL Zoo 6.The JOIN operation
  • 【c++】类和对象 (中) (类的默认成员函数)
  • Springboot 实现 Modbus Rtu 协议接入物联网设备
  • matlab实现红绿灯识别
  • MySQL事务隔离级别、InnoDB使用MVCC+各种锁实现了RC和RR事务隔离级别、具体案例
  • cpio 命令
  • element-ui周选择器,如何获取年、周、起止日期?
  • C# Type 对象序列化与反序列化
  • 合并两个有序数组(LeetCode)
  • oracle创建dblink使得数据库A能够访问数据库B表LMEAS_MFG_FM的数据
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【mysql】环境安装、服务启动、密码设置
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • CentOS6 编译安装 redis-3.2.3
  • Git同步原始仓库到Fork仓库中
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • js学习笔记
  • laravel 用artisan创建自己的模板
  • laravel5.5 视图共享数据
  • spring + angular 实现导出excel
  • webpack+react项目初体验——记录我的webpack环境配置
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 阿里云购买磁盘后挂载
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 工程优化暨babel升级小记
  • 工作中总结前端开发流程--vue项目
  • 和 || 运算
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 删除表内多余的重复数据
  • 事件委托的小应用
  • 学习JavaScript数据结构与算法 — 树
  • ​configparser --- 配置文件解析器​
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​ssh免密码登录设置及问题总结
  • ​卜东波研究员:高观点下的少儿计算思维
  • # Java NIO(一)FileChannel
  • # 数据结构
  • #laravel 通过手动安装依赖PHPExcel#
  • #QT项目实战(天气预报)
  • (LeetCode C++)盛最多水的容器
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (二)WCF的Binding模型
  • (附源码)ssm高校社团管理系统 毕业设计 234162
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (篇九)MySQL常用内置函数
  • (七)Appdesigner-初步入门及常用组件的使用方法说明
  • (七)理解angular中的module和injector,即依赖注入
  • (入门自用)--C++--抽象类--多态原理--虚表--1020