SpringBoot 中使用 @Async 实现异步调用​


SpringBoot 中使用 @Async 实现异步调用

  • 一、@Async 注解的使用场合​
  • 二、@Async 注解的创建与调试​
  • 三、@Async 注解的注意事项​
  • 四、总结​


在高并发、高性能要求的应用场景下,异步处理能够显著提升系统的响应速度和吞吐量。Spring Boot 提供的 @Async 注解为开发者实现异步调用提供了便捷方式。本文将深入探讨 @Async 注解的使用场合、创建调试流程以及相关注意事项,帮助你在项目中优雅地运用异步调用。​

一、@Async 注解的使用场合​

  1. 耗时任务处理​
    当应用程序中存在一些耗时较长的任务,如文件上传后的处理、大数据量的计算、第三方接口调用等,如果采用同步处理,会导致主线程阻塞,影响用户体验。此时使用 @Async 注解将这些任务异步执行,主线程无需等待任务完成,可立即返回响应,提高系统的响应速度。例如,在电商系统中,用户下单后,可能需要进行库存更新、积分计算、订单消息推送等一系列操作,其中积分计算和消息推送等操作可以异步执行,不影响订单处理的主流程。​
  2. 日志记录​
    日志记录是应用程序中常见的功能,但频繁的磁盘 I/O 操作会影响系统性能。将日志记录操作异步化,使用 @Async 注解标记日志记录方法,能避免因日志写入而阻塞主线程,保证业务逻辑的高效执行。例如,在高并发的 Web 应用中,大量的访问日志记录如果同步进行,会对系统性能产生较大影响,异步记录日志则可有效解决这一问题。​
  3. 消息通知​
    在系统中发送邮件、短信、推送消息等通知功能时,这些操作通常不需要立即得到结果,且可能会因网络等原因耗时较长。通过 @Async 注解将消息通知方法设置为异步执行,可使系统在发送通知的同时继续处理其他业务,提升整体效率。比如在社交应用中,用户发布动态后,系统需要向关注该用户的其他用户发送通知,异步发送通知可以减少用户等待时间。​
  4. 缓存更新​
    当数据发生变化时,需要更新对应的缓存。缓存更新操作可能涉及多个缓存节点的操作,耗时较长。将缓存更新方法标注为异步,能让数据更新操作在后台进行,不影响业务逻辑的正常执行,保证系统的高可用性。例如在分布式缓存系统中,更新缓存可能需要与多个缓存服务器进行交互,异步处理可提高系统性能。​

二、@Async 注解的创建与调试​

  1. 启用异步支持​
    在 Spring Boot 项目中,要使用 @Async 注解,首先需要在配置类上添加 @EnableAsync 注解,启用异步支持。例如:​
import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.EnableAsync;​
​
@Configuration@EnableAsyncpublic class AsyncConfig {// 可在此处进行更多异步相关的配置,如线程池配置​
}

上述代码创建了一个配置类 AsyncConfig,并通过 @EnableAsync 注解开启了 Spring Boot 的异步功能。​

  1. 使用 @Async 注解标记异步方法​
    在需要异步执行的方法上添加 @Async 注解。通常在 Service 层的方法上使用,示例如下:​
import org.springframework.scheduling.annotation.Async;import org.springframework.stereotype.Service;​
​
@Servicepublic class AsyncService {​
​@Asyncpublic void asyncTask() {// 模拟耗时操作​try {Thread.sleep(3000);} catch (InterruptedException e) {​e.printStackTrace();}System.out.println("异步任务执行完成");}}


在上述代码中,AsyncService 类的 asyncTask 方法被 @Async 注解标记,该方法将异步执行。​

  1. 调用异步方法​
    在其他组件中注入 AsyncService 并调用异步方法,例如在 Controller 中调用:​
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;​
​
@RestControllerpublic class AsyncController {​
​@Autowiredprivate AsyncService asyncService;​
​@GetMapping("/async")public String async() {​asyncService.asyncTask();return "异步任务已提交";}}


当访问 /async 接口时,asyncTask 方法会异步执行,主线程立即返回响应。​

  1. 调试异步方法​
    调试异步方法时,由于异步方法在新的线程中执行,常规的断点调试可能无法直接命中。可以采用以下方法进行调试:​
    日志输出:在异步方法中添加详细的日志输出,通过日志信息了解方法的执行流程和变量值。例如在 asyncTask 方法中添加 System.out.println 语句输出关键步骤的信息。​
    调试工具设置:在 IDE 中进行特定设置,如在 IntelliJ IDEA 中,在 Run/Debug Configurations 中,找到对应的启动配置,在 VM options 中添加 -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005,然后以调试模式启动项目,使用远程调试工具连接到指定端口进行调试。​
    异常处理:在异步方法中添加合适的异常处理代码,当异步任务出现异常时,通过捕获异常并输出异常信息,定位问题所在。例如:​
import org.springframework.scheduling.annotation.Async;import org.springframework.stereotype.Service;​
​
@Servicepublic class AsyncService {​
​@Asyncpublic void asyncTask() {try {// 模拟耗时操作​Thread.sleep(3000);// 模拟可能出现的异常​int result = 1 / 0;} catch (InterruptedException e) {​e.printStackTrace();} catch (Exception e) {System.out.println("异步任务执行出错:" + e.getMessage());}System.out.println("异步任务执行完成");}}​
​

三、@Async 注解的注意事项​

  1. 线程池配置​
    默认情况下,@Async 使用 Spring 内置的简单线程池,在高并发场景下可能无法满足需求。建议根据实际业务情况配置自定义线程池,通过实现 AsyncConfigurer 接口来配置线程池的核心线程数、最大线程数、队列容量等参数。示例如下:​
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.AsyncConfigurer;import org.springframework.scheduling.annotation.EnableAsync;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;​
​
import java.util.concurrent.Executor;​
​
@Configuration@EnableAsyncpublic class AsyncConfig implements AsyncConfigurer {​
​@Override@Beanpublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();​executor.setCorePoolSize(5);​executor.setMaxPoolSize(10);​executor.setQueueCapacity(200);​executor.setThreadNamePrefix("Async-");​executor.initialize();return executor;}}​
​

上述代码配置了一个核心线程数为 5,最大线程数为 10,队列容量为 200 的线程池。​

  1. 异常处理​
    异步方法中抛出的异常不会被调用方直接捕获,如果不进行特殊处理,异常可能会被忽略。可以通过两种方式处理异步方法中的异常:​
    使用 Future 接收返回值:将异步方法的返回值类型改为 Future,通过 Future 的 get 方法获取异步任务的执行结果,在获取结果时捕获异常。例如:​
import org.springframework.scheduling.annotation.Async;import org.springframework.stereotype.Service;import java.util.concurrent.Future;​
​
@Servicepublic class AsyncService {​
​@Asyncpublic Future<String> asyncTask() {try {// 模拟耗时操作​Thread.sleep(3000);// 模拟可能出现的异常​int result = 1 / 0;return new java.util.concurrent.FutureTask<>(() -> "任务成功");} catch (InterruptedException e) {​e.printStackTrace();} catch (Exception e) {// 可以在这里进行异常处理或记录日志​}return null;}}​
​

在调用方获取 Future 结果时捕获异常:​

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.ExecutionException;import java.util.concurrent.Future;​
​
@RestControllerpublic class AsyncController {​
​@Autowiredprivate AsyncService asyncService;​
​@GetMapping("/async")public String async() {Future<String> future = asyncService.asyncTask();try {String result = future.get();return result;} catch (InterruptedException | ExecutionException e) {​e.printStackTrace();return "异步任务执行出错";}}}


自定义异常处理机制:实现 AsyncUncaughtExceptionHandler 接口,自定义异步方法未捕获异常的处理逻辑。例如:​

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;import java.lang.reflect.Method;​
​
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {​
​@Overridepublic void handleUncaughtException(Throwable throwable, Method method, Object... obj) {System.out.println("异步方法 [" + method.getName() + "] 抛出异常:" + throwable.getMessage());// 可以在此处添加更详细的异常处理逻辑,如记录日志、发送告警等​}}​
​

在 AsyncConfig 中配置自定义的异常处理器:​

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.AsyncConfigurer;import org.springframework.scheduling.annotation.EnableAsync;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;​
​
import java.util.concurrent.Executor;​
​
@Configuration@EnableAsyncpublic class AsyncConfig implements AsyncConfigurer {​
​@Override@Beanpublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();​executor.setCorePoolSize(5);​executor.setMaxPoolSize(10);​executor.setQueueCapacity(200);​executor.setThreadNamePrefix("Async-");​executor.initialize();return executor;}​
​@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return new CustomAsyncExceptionHandler();}}
  1. 类内部调用问题​
    在同一个类中,直接调用被 @Async 注解标记的方法,异步调用不会生效。因为 Spring 是通过代理机制实现 @Async 功能的,类内部调用无法触发代理,也就无法实现异步。解决方法是将异步方法提取到独立的类中,通过依赖注入的方式调用。​

  2. 事务管理​
    当异步方法涉及事务操作时,需要注意事务的传播行为和生效范围。默认情况下,异步方法开启新的事务,与调用方的事务相互独立。如果需要在异步方法中共享调用方的事务,可通过设置事务传播行为为 REQUIRES_NEW 或 NESTED 来实现。同时,确保事务管理器在异步线程中正确配置和生效。​

四、总结​

@Async 注解为 Spring Boot 应用实现异步调用提供了简洁高效的方式,合理运用能显著提升系统性能和用户体验。在使用过程中,要根据具体业务场景选择合适的使用场合,掌握正确的创建调试方法,并注意线程池配置、异常处理、类内部调用、事务管理等方面的问题。通过深入理解和熟练运用 @Async 注解,让你的 Spring Boot 项目在处理异步任务时更加优雅和高效。​
希望以上内容能帮助你在项目中更好地使用 @Async 注解。如果你在实践中有任何疑问,或者想了解更多相关技巧,欢迎在评论区交流分享。​
以上内容涵盖了@Async注解多方面要点,能助你掌握其用法。若你对文中某个部分想深入探讨,或有其他补充需求,欢迎随时说。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/86623.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/86623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CMOS SENSOR HDR场景下MIPI 虚拟端口的使用案例

CMOS SENSOR HDR场景下MIPI 虚拟端口的使用案例 文章目录 CMOS SENSOR HDR场景下MIPI 虚拟端口的使用案例📷 **一、HDR模式下的虚拟通道核心作用**⚙️ **二、典型应用案例****1. 车载多目HDR系统****2. 工业检测多模态HDR****3. 手机多摄HDR合成**🔧 **三、实现关键技术点…

RJ45 以太网与 5G 的原理解析及区别

一、RJ45 以太网的原理 1. RJ45 接口与以太网的关系 RJ45 是一种标准化的网络接口&#xff0c;主要用于连接以太网设备&#xff08;如电脑、路由器&#xff09;&#xff0c;其物理形态为 8 针模块化接口&#xff0c;适配双绞线&#xff08;如 CAT5、CAT6 网线&#xff09;。以…

valkey之sdscatrepr 函数优化解析

一、函数功能概述 sds sdscatrepr(sds s, const char *p, size_t len)函数的核心功能是将字符串p追加到字符串s中。在追加过程中&#xff0c;它会对字符串p中的字符进行判断&#xff0c;使用isprint()函数识别不可打印字符&#xff0c;并对这些字符进行转义处理&#xff0c;确…

MyBatis 缓存机制详解

MyBatis 缓存机制详解 MyBatis 提供了强大的缓存机制来提高数据库访问性能&#xff0c;主要包括一级缓存和二级缓存两种。 一级缓存 (Local Cache) 特性&#xff1a; 默认开启&#xff0c;作用域为 SqlSession 级别同一个 SqlSession 中执行相同的 SQL 查询时&#xff0c;会…

设计模式精讲 Day 13:责任链模式(Chain of Responsibility Pattern)

【设计模式精讲 Day 13】责任链模式&#xff08;Chain of Responsibility Pattern&#xff09; 文章内容 在“设计模式精讲”系列的第13天&#xff0c;我们将深入讲解责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;。这是一种行为型设计模式&#xff0c;…

h-ui面板 hysteria2

搭建文档 项目地址&#xff1a;https://github.com/jonssonyan/h-ui/blob/main/README_ZH.md参考视频&#xff1a;https://www.youtube.com/watch?vNi3iaLOsH_A一键部署命令 # root权限 sudo -ibash <(curl -fsSL https://raw.githubusercontent.com/jonssonyan/h-ui/mai…

自动登录脚本神器-Mac电脑实现自动登录堡垒机并自动输入账号密码跳转不同机器环境

先讲下背景&#xff1a; 公司电脑需要先登录堡垒机&#xff0c;然后再从堡垒机跳转到具体生产机器&#xff0c;每次输入堡垒机都要通过Authenticator里的2FC的码做验证&#xff0c;然后再跳到堡垒机还要再输入一次账号密码&#xff0c;为了方便快速登录机器&#xff0c;可以制…

【C/C++】C++26新特性前瞻:全面解析未来编程

展望未来&#xff1a;C26 新特性全面解析 随着 C 标准每三年一次的迭代节奏&#xff0c;C26&#xff08;预计于 2026 年底正式发布&#xff09;正在逐步成型。相比 C20 的革命性更新和 C23 的“修补增强”&#xff0c;C26 继续推进现代 C 的理念——更安全、更高效、更模块化&…

ArXiv 2101 | Rethinking Interactive Image Segmentation Feature Space Annotation

Rethinking Interactive Image Segmentation Feature Space Annotation Author: lartpangLink: https://github.com/lartpang/blog/issues/10论文&#xff1a;https://arxiv.org/abs/2101.04378代码&#xff1a;https://github.com/LIDS-UNICAMP/rethinking-interactive-image…

架构经验总结

20250511-总结经验 一、SOA 1&#xff09;过程&#xff1a;需求分析、系统设计、系统实现、构件组装、部署运维、后开发阶段。 2&#xff09;特点&#xff1a;无状态、单一职责、明确定义接口、自包含、模块化、粗粒度、重用性、兼容性、互操作性、松耦合、策略声明。 3&…

debain切换 opensuse 我都安装了什么

绿色进度条后&#xff0c;黑屏&#xff08;只有一个下划线&#xff09;等待 使用 nomodeset 属性解决 进入系统无法连接 wifi&#xff0c;只能使用网线连接 wifi 这个我在安装中文字体后&#xff0c;注销登录&#xff0c;得到了解决&#xff0c;不确定是不是字体问题。&#x…

思科ISE/ISE-PIC安全警报:两处高危RCE漏洞(CVSS 10.0)可致未授权获取root权限

思科已发布更新&#xff0c;修复身份服务引擎&#xff08;Identity Services Engine&#xff0c;ISE&#xff09;及ISE被动身份连接器&#xff08;ISE-PIC&#xff09;中两处最高危安全漏洞&#xff0c;这些漏洞可能允许未经认证的攻击者以root用户身份执行任意命令。 漏洞详情…

智能助手(利用GPT搭建智能系统)

项目介绍 本项目旨在打造一个基于通义千问模型的智能助手&#xff0c;能够理解用户指令并自动生成可执行的 JavaScript 代码。该代码可直接调用预设接口&#xff0c;完成指定操作&#xff0c;并返回执行结果。通过大模型的理解与生成能力&#xff0c;实现从自然语言到接口调用…

【源码+文档+调试讲解】基于web的运动健康小程序的设计与实现y196

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对高校教师成果信息管理混乱&#xff0c;出错率高&#xff0c;信息安全…

临床项目计划框架

一、项目概述 1.1 项目名称 项目名称:评估XX药物在YY患者中安全性和有效性的III期随机对照试验 1.2 项目背景与立项依据 1.2.1 研究背景 简述疾病负担、当前治疗现状、未满足的医疗需求,为项目开展提供背景支持。 1.2.2 科学依据 总结前期研究结果、理论基础、研究假设的形…

Hoare逻辑与分离逻辑:从程序验证到内存推理的演进

文章目录 引言一、Hoare逻辑基础&#xff1a;程序正确性的形式化验证&#x1f330; 例子&#xff1a;简单赋值语句的Hoare逻辑验证&#x1f330; 例子&#xff1a;条件语句的Hoare逻辑验证 二、分离逻辑&#xff1a;Hoare逻辑在内存管理中的扩展&#x1f50d; 分离逻辑的核心扩…

Tomcat Maven 插件

在 Maven 项目中&#xff0c;可以使用 Tomcat Maven 插件&#xff08;tomcat7-maven-plugin 或 tomcat-maven-plugin&#xff09;来直接部署 WAR 文件到 Tomcat 服务器&#xff0c;而无需手动复制 WAR 文件到 webapps 目录。以下是详细的使用方法&#xff1a; 1. 配置 Tomcat M…

【开源工具】一键解决使用代理后无法访问浏览器网页问题 - 基于PyQt5的智能代理开关工具开发全攻略

&#x1f310;【开源工具】一键解决使用代理后无法访问浏览器网页问题 - 基于PyQt5的智能代理开关工具开发全攻略 &#x1f308; 个人主页&#xff1a;创客白泽 - CSDN博客 &#x1f525; 系列专栏&#xff1a;&#x1f40d;《Python开源项目实战》 &#x1f4a1; 热爱不止于代…

异步IO框架io_uring实现TCP服务器

一、io_uring介绍 io_uring是 Linux 于 2019 年加入到内核的一种新型异步 I/O 模型&#xff0c;io_uring 主要为了解决 原生AIO&#xff08;Native AIO&#xff09; 存在的一些不足之处。下面介绍一下原生 AIO 的不足之处&#xff1a; 系统调用开销大&#xff1a;提交 I/O 操作…

【docker】docker run参数说明

功能 拉起容器。 参数 -i&#xff0c;--interactive 保持容器标准输入放开&#xff0c;就算没有终端也放开。 可以理解为可以向容器内输入东西&#xff0c;比如&#xff1a; [rootlocalhost ~]# echo 111 | docker run -i yaxin:1.0 cat 111--cap-add 用于向容器添加特定的…