Spring Boot中@Async注解的使用及原理 + 常见问题及解决方案

在这里插入图片描述

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
🎐 个人CSND主页——Micro麦可乐的博客
🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
🌺《RabbitMQ》专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
💕《Jenkins实战》专栏主要介绍Jenkins+Docker的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程
🌞《Spring Boot》专栏主要介绍我们日常工作项目中经常应用到的功能以及技巧,代码样例完整
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

Spring Boot中@Async注解的使用以及注意事项

  • 1、前言
  • 2、@Async注解的基本使用
    • ❶ 引入依赖
    • ❷ 启用异步支持
    • ❸ 定义异步方法
    • ❹ 调用异步方法
  • 3、@Async注解的实现原理
    • ❶ TaskExecutor
    • ❷ AOP代理
    • ❸ 异步方法返回值
  • 4、应用场景
    • ❶ 后台任务处理
    • ❷ 并行处理
    • ❸ 提高系统吞吐量
  • 5、常见问题及解决方案
    • 5.1、@Async方法调用无效
    • 5.2、异常处理
  • 6、结语

1、前言

在现代Java应用程序中,异步处理是提高性能和响应速度的重要手段之一,比如博主之前分享的【Spring Boot 使用自定义注解和自定义线程池实现异步日志记录】,就是采用了异步处理来实现日志记录,而在Spring Boot中它提供了@Async注解来简化异步编程,今天博主就来和小伙伴们分享本@Async注解的基本使用、实现原理以及应用场景。


2、@Async注解的基本使用

@Async注解用于标注方法,使其在独立的线程中异步执行。Spring Boot提供了一种简单的方法来启用异步方法调用,只需在配置类或主类上添加@EnableAsync注解

❶ 引入依赖

Spring Boot 项目 pom.xml 文件中添加必要的依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

❷ 启用异步支持

在Spring Boot应用的配置类或主类上启用异步支持 @EnableAsync

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;@SpringBootApplication
@EnableAsync
public class AsyncApplication {public static void main(String[] args) {SpringApplication.run(AsyncApplication.class, args);}
}

❸ 定义异步方法

使用@Async注解定义异步方法。例如:创建一个服务类AsyncService

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;@Service
public class AsyncService {@Asyncpublic void asyncMethod() {try {Thread.sleep(5000); // 模拟耗时操作} catch (InterruptedException e) {e.printStackTrace();}System.out.println("异步方法执行完成");}
}

❹ 调用异步方法

在需要调用异步方法的地方,通过注入AsyncService并调用其异步方法

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class AsyncController {@Autowiredprivate AsyncService asyncService;@GetMapping("/async")public String callAsyncMethod() {asyncService.asyncMethod();return "异步方法已调用";}
}

最后请求访问Controller/api/async , 会发现Controller立即返回响应,而asyncMethod将在独立线程中执行,5秒后控制台输出:异步方法执行完成


3、@Async注解的实现原理

@Async注解的实现依赖于Spring的AOP(面向切面编程)和TaskExecutor

❶ TaskExecutor

Spring 使用TaskExecutor来处理异步任务。默认情况下,Spring Boot使用SimpleAsyncTaskExecutor,但我们也可以自定义TaskExecutor来控制线程池

自定义TaskExecutor
我们可以通过@Bean注解定义自定义的TaskExecutor

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;@Configuration
public class AsyncConfig {@Bean(name = "taskExecutor")public Executor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(25);executor.setThreadNamePrefix("AsyncThread-");executor.initialize();return executor;}
}

❷ AOP代理

@Async注解通过Spring AOP代理来实现异步调用。当标注为@Async的方法被调用时,Spring AOP会拦截调用并在TaskExecutor的线程池中异步执行该方法

❸ 异步方法返回值

@Async注解的方法可以返回voidFutureCompletableFuture等类型,如下代码

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;@Service
public class AsyncService {@Asyncpublic CompletableFuture<String> asyncMethodWithReturn() {try {Thread.sleep(5000); // 模拟耗时操作} catch (InterruptedException e) {e.printStackTrace();}return CompletableFuture.completedFuture("异步方法返回结果");}
}

调用带返回值的异步方法:

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.CompletableFuture;@RestController
public class AsyncController {@Autowiredprivate AsyncService asyncService;@GetMapping("/asyncWithReturn")public CompletableFuture<String> callAsyncMethodWithReturn() {return asyncService.asyncMethodWithReturn();}
}

4、应用场景

@Async注解适用于各种需要异步处理的场景,例如:

❶ 后台任务处理

在Web应用中,有些任务(如发送邮件生成报告)耗时较长,可以使用@Async异步处理,使用户无需等待任务完成即可获得响应。

❷ 并行处理

对于可以并行处理的任务,如并行数据处理、并行调用多个外部服务,使用@Async可以提高效率。

❸ 提高系统吞吐量

通过异步调用,可以充分利用多线程资源,提高系统的吞吐量和响应速度。


5、常见问题及解决方案

5.1、@Async方法调用无效

如果在同一个类中调用@Async注解的方法,异步调用可能无效。这是因为Spring AOP代理无法拦截同一类中的@Async

解决方法:将异步方法放到另一个类中,通过依赖注入进行调用

5.2、异常处理

异步方法中的异常不会自动传播到调用方。可以使用CompletableFuture处理异常,见下面演示代码

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;@Service
public class AsyncService {@Asyncpublic CompletableFuture<String> asyncMethodWithException() {try {Thread.sleep(5000); // 模拟耗时操作throw new RuntimeException("异常发生");} catch (InterruptedException e) {e.printStackTrace();}return CompletableFuture.completedFuture("异步方法完成");}
}

处理异常:

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.CompletableFuture;@RestController
public class AsyncController {@Autowiredprivate AsyncService asyncService;@GetMapping("/asyncWithException")public CompletableFuture<String> callAsyncMethodWithException() {return asyncService.asyncMethodWithException().exceptionally(ex -> "处理异常:" + ex.getMessage());}
}

6、结语

Spring Boot@Async注解提供了一种简洁且强大的方式来实现异步处理。通过启用异步支持、定义异步方法并自定义TaskExecutor,可以高效地处理各种异步任务。掌握@Async注解的使用和原理,有助于提升应用程序的性能和响应速度。

如果本文对您有所帮助,希望 一键三连 给博主一点点鼓励,如果您有任何疑问或建议,请随时留言讨论!


在这里插入图片描述

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

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

相关文章

阿里云GPU服务器安装ComfyUI

连接到GPU服务器: 使用SSH客户端(如PuTTY或终端)连接到你的服务器。命令通常是: ssh usernameserver_ip安装依赖: 确保Python和Git已安装。在大多数Linux系统上,可以这样安装: sudo apt update sudo apt install python3 python3-pip git克隆ComfyUI仓库: 这步骤会下载ComfyUI的…

Jetson-AGX-Orin 非docker环境源码编译安装CyberRT

Jetson-AGX-Orin 非docker环境源码编译安装CyberRT 1、安装依赖 sudo apt update sudo apt-get install g gdb gcc cmake sudo apt install libpoco-dev uuid-dev libncurses5-dev python3-dev python3-pip python3 -m pip install protobuf3.14.02、下载CyberRT源码 git cl…

C语言 ——— 大/小端存储模式的介绍及判断

目录 何为大端小端 如何测试当前机器是大端还是小端 编写代码&#xff0c;判断当前机器的字节序 何为大端小端 大端字节序存储模式&#xff1a;数据的低位字节的内容 存放在 内存的高地址 中&#xff0c;数据的高位字节的内容 保存在 内存的低地址 中 小端字节序存储模式&am…

【系统架构设计师】九、软件工程(面向对象方法|逆向工程)

目录 六、面向对象方法 6.1 基本概念 6.2 面向对象的分析 6.2.1 用例关系 6.2.2 类之间的关系 6.3 面向对象的设计 6.4 面向对象设计原则与设计模式 6.5 面向对象软件的测试 七、逆向工程 历年真题练习 六、面向对象方法 面向对象的分析方法 (Object-Oriented Analys…

Vue从零到实战

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

《后端程序员 · Nacos 常见配置 · 第一弹》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

showdoc sqli to rce漏洞利用思考

漏洞版本 sqli <3.2.5 phar 反序列化 <3.2.4 漏洞分析 前台sqli 补丁 https://github.com/star7th/showdoc/commit/84fc28d07c5dfc894f5fbc6e8c42efd13c976fda 补丁对比发现&#xff0c;在server/Application/Api/Controller/ItemController.class.php中将$item_id变量…

海外ASO:iOS与谷歌优化的相同点和区别

海外ASO是针对iOS的App Store和谷歌的Google Play这两个主要海外应用商店进行的优化过程&#xff0c;两个不同的平台需要采取不同的优化策略&#xff0c;以下是对iOS优化和谷歌优化的详细解析&#xff1a; 一、iOS优化&#xff08;App Store&#xff09; 1、关键词覆盖 选择关…

服务器数据恢复—raid5阵列热备盘同步失败导致lun不可用的数据恢复案例

服务器存储数据恢复环境&#xff1a; 华为S5300存储中有一组由16块FC硬盘组建的RAID5磁盘阵列&#xff08;包含一块热备盘&#xff09;。 服务器存储故障&#xff1a; 该存储中的RAID5阵列1块硬盘由于未知原因离线&#xff0c;热备盘上线并开始同步数据&#xff0c;数据同步到…

starRocks搭建

公司要使用新的大数据架构&#xff0c;打算用国产代替国外的大数据平台。所以这里我就纠结用doris还是starrocks&#xff0c;如果用doris&#xff0c;因为是开源的&#xff0c;以后就可以直接用云厂商的。如果用starrocks就得自己搭建&#xff0c;但是以后肯定会商业化&#xf…

【linux】服务器ubuntu安装cuda11.0、cuDNN教程,简单易懂,包教包会

【linux】服务器ubuntu安装cuda11.0、cuDNN教程&#xff0c;简单易懂&#xff0c;包教包会 【创作不易&#xff0c;求点赞关注收藏】 文章目录 【linux】服务器ubuntu安装cuda11.0、cuDNN教程&#xff0c;简单易懂&#xff0c;包教包会一、版本情况介绍二、安装cuda1、到官网…

最新PHP自助商城源码,彩虹商城源码

演示效果图 后台效果图 运行环境&#xff1a; Nginx 1.22.1 Mysql5.7 PHP7.4 直接访问域名即可安装 彩虹自助下单系统二次开发 拥有供货商系统 多余模板删除 保留一套商城,两套发卡 源码无后门隐患 已知存在的BUG修复 彩虹商城源码&#xff1a;下载 密码:chsc 免责声明&…

「AI得贤招聘官」通过首批“AI产业创新场景应用案例”评估

近日&#xff0c;上海近屿智能科技有限公司的「AI得贤招聘官」&#xff0c;经过工业和信息化部工业文化发展中心数字科技中心的严格评估&#xff0c;荣获首批“AI产业创新场景应用案例”。 据官方介绍&#xff0c;为积极推进通用人工智能产业高质量发展&#xff0c;围绕人工智能…

浅析Kafka Streams消息流式处理流程及原理

以下结合案例&#xff1a;统计消息中单词出现次数&#xff0c;来测试并说明kafka消息流式处理的执行流程 Maven依赖 <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-streams</artifactId><exclusio…

kafka发送消息流程

配置props.put(ProducerConfig.PARTITIONER_CLASS_CONFIG, RoundRobinPartitioner.class); public Map<String,Object> producerConfigs(){Map<String,Object> props new HashMap<>();props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,bootstrapServers…

文件的顺序读写

文件读写函数介绍 文件顺序读写函数 函数名功能适用于fputc 字符输出函数 所有输出流 fgetc 字符输⼊函数 所有输⼊流 fputs ⽂本⾏输出函数 所有输出流fgets ⽂本⾏输⼊函数 所有输⼊流fprintf 格式化输出函数 所有输出流fscanf 格式化输⼊函数 所有输⼊流fwrite ⼆进制输出…

Spring源码中的模板方法模式

1. 什么是模板方法模式 模板方法模式&#xff08;Template Method Pattern&#xff09;是一种行为设计模式&#xff0c;它在操作中定义算法的框架&#xff0c;将一些步骤推迟到子类中。模板方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。 模板方法模式的定义&…

被动的机器人非线性MPC控制

MPC是一种基于数学模型的控制策略&#xff0c;它通过预测系统在未来一段时间内的行为&#xff0c;并求解优化问题来确定当前的控制输入&#xff0c;以实现期望的控制目标。对于非线性系统&#xff0c;MPC可以采用非线性模型进行预测和优化&#xff0c;这种方法被称为非线性模型…

DBeaver导入脚本和导出数据

DBeaver导入脚本和导出数据 前言&#xff1a; 通常产品会要求&#xff0c;把xx表导出Excel&#xff0c;navicat一般公司不让用。讲解使用DBeaver 导入脚本 我们将sql脚本导入DBeaver 1&#xff0c;选择数据库&#xff0c;找到执行脚本 2&#xff0c;选用sql脚本&#xff0…

【Linux】权限管理与相关指令

文章目录 1.权限、文件权限、用户文件权限的理解以及对应八进制数值表示、设置目录为粘滞位文件类型 2.权限相关的常用指令susudochmodchownchgrpumaskwhoamifile 1.权限、文件权限、用户 通过一定条件&#xff0c;拦住一部分人&#xff0c;给另一部分权利来访问资源&#xff0…