SpringBoot中@EnableAsync和@Async注解的使用

news/2024/4/26 19:08:24/文章来源:https://blog.csdn.net/qq_33204709/article/details/130353652

目录

    • 1.@EnableAsync 注解
      • 1.1 配置类使用示例
      • 1.2 复制请求上下文
    • 2.用法1:@Async 注解
      • 2.1 测试Controller
      • 2.2 测试Service
      • 2.3 测试ServiceImpl
      • 2.4.测试
    • 4.用法2:直接使用 taskExecutor 做异步
      • 4.1 重新实现:测试ServiceImpl
      • 4.2 测试
    • 5.@Async异步不生效原因

在 Spring Boot 中,可以通过 @EnableAsync 注解来启动异步方法调用的支持,通过 @Async 注解来标识异步方法,让方法能够在异步线程中执行。下面分别介绍它们的使用方法。

1.@EnableAsync 注解

@EnableAsync 是一个 Spring Boot 中用于启动异步方法调用的注解。使用 @EnableAsync 注解时,需要将其放置在一个配置类上,并且在配置类中通过 @Bean 方法创建一个线程池。

下面举个例子:

1.1 配置类使用示例

AsyncTaskExecutorConfig 类通过 @EnableAsync 注解来启用异步方法调用,然后在配置类中通过 @Bean 方法创建了一个名为 asyncExecutor 的线程池,用于执行异步方法。

import com.demo.async.ContextCopyingDecorator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;/*** <p> @Title AsyncTaskExecutorConfig* <p> @Description 异步线程池配置** @author ACGkaka* @date 2023/4/24 19:48*/
@EnableAsync
@Configuration
public class AsyncTaskExecutorConfig {/*** 核心线程数(线程池维护线程的最小数量)*/private int corePoolSize = 10;/*** 最大线程数(线程池维护线程的最大数量)*/private int maxPoolSize = 200;/*** 队列最大长度*/private int queueCapacity = 10;@Beanpublic TaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(corePoolSize);executor.setMaxPoolSize(maxPoolSize);executor.setQueueCapacity(queueCapacity);executor.setThreadNamePrefix("MyExecutor-");// for passing in request scope context 转换请求范围的上下文executor.setTaskDecorator(new ContextCopyingDecorator());// rejection-policy:当pool已经达到max size的时候,如何处理新任务// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.setWaitForTasksToCompleteOnShutdown(true);executor.initialize();return executor;}
}

1.2 复制请求上下文

ContextCopyingDecorator 类使用了装饰者模式,用于将主线程中的请求上下文拷贝到异步子线程中,并且在异步子线程执行之后清空请求的上下文。

import org.slf4j.MDC;
import org.springframework.core.task.TaskDecorator;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;import java.util.Map;/*** <p> @Title ContextCopyingDecorator* <p> @Description 上下文拷贝装饰者模式** @author ACGkaka* @date 2023/4/24 20:20*/
public class ContextCopyingDecorator implements TaskDecorator {@Overridepublic Runnable decorate(Runnable runnable) {try {// 从父线程中获取上下文,然后应用到子线程中RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();Map<String, String> previous = MDC.getCopyOfContextMap();SecurityContext securityContext = SecurityContextHolder.getContext();return () -> {try {if (previous == null) {MDC.clear();} else {MDC.setContextMap(previous);}RequestContextHolder.setRequestAttributes(requestAttributes);SecurityContextHolder.setContext(securityContext);runnable.run();} finally {// 清除请求数据MDC.clear();RequestContextHolder.resetRequestAttributes();SecurityContextHolder.clearContext();}};} catch (IllegalStateException e) {return runnable;}}
}

2.用法1:@Async 注解

@Async 注解是一个 Spring Boot 中用于标识异步方法的注解,通过在方法上添加 @Async 注解,可以让该方法在异步线程中执行。

下面举个例子:

2.1 测试Controller

DemoController 类中声明了 /demo/test 接口,接口中调用了 demoService.testError() 方法。

import com.demo.common.Result;
import com.demo.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** <p> @Title DemoController* <p> @Description 测试Controller** @author ACGkaka* @date 2023/4/24 18:02*/
@RestController
@RequestMapping("/demo")
public class DemoController {@Autowiredprivate DemoService demoService;@RequestMapping("/test")public Result<Object> test() {Result<Object> result = Result.succeed();System.out.println("start...");demoService.testError();System.out.println("end...");return result;}
}

2.2 测试Service

/*** <p> @Title DemoService* <p> @Description 测试Service** @author ACGkaka* @date 2023/4/24 18:13*/
public interface DemoService {/*** 测试异常*/void testError() throws InterruptedException;
}

2.3 测试ServiceImpl

DemoServiceImpl 类使用了 @Async 注解,用于异步调用,testError() 方法中抛出了异常,用于测试异步执行。

这里 @Async 注解的 value 值指定了我们在配置类中声明的 taskExecutor 线程池。

  • 假如只配置了一个线程池,直接用 @Async 注解就会用自定义的线程池执行。
  • 假如配置了多个线程池,用 @Async("name") 来指定使用哪个线程池,如果没有指定,会用默认的 SimpleAsyncTaskExecutor 来处理。
import com.demo.service.DemoService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;/*** <p> @Title DemoServiceImpl* <p> @Description 测试ServiceImpl** @author ACGkaka* @date 2023/4/24 18:14*/
@Service
public class DemoServiceImpl implements DemoService {@Async("taskExecutor")@Overridepublic void testError() throws InterruptedException {throw new RuntimeException("测试异常");}
}

2.4.测试

访问接口:http://localhost:8080/demo/test

访问结果如下,可见异常并没有接口返回正常的结果,异步测试成功。

在这里插入图片描述

4.用法2:直接使用 taskExecutor 做异步

由于我们在第1步中,将异步线程池注入到了 taskExecutor Bean 容器中,我们就可以直接通过 @Autowired 或者 @Resource 获取到线程池,然后使用。

我们通过直接使用 taskExecutor 线程池的方式,重新实现 DemoServiceImpl.java:

4.1 重新实现:测试ServiceImpl

import com.demo.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;/*** <p> @Title DemoServiceImpl* <p> @Description 测试ServiceImpl** @author ACGkaka* @date 2023/4/24 18:14*/
@Service
public class DemoServiceImpl implements DemoService {@Qualifier("taskExecutor")@Autowiredprivate TaskExecutor taskExecutor;@Overridepublic void testError() {taskExecutor.execute(() -> {throw new RuntimeException("测试异常");});}
}

4.2 测试

访问接口:http://localhost:8080/demo/test

访问结果如下,可见异常并没有接口返回正常的结果,异步测试成功,直接使用线程池的方式也可行。

在这里插入图片描述

在这里插入图片描述

5.@Async异步不生效原因

1)@SpringBootApplication 启动类或配置类当中没有添加 @EnableAsync 注解。

(补充:项目中除了启动类和配置类外,任何一个注入到 Bean 容器中的类添加 @EnableAsync 注解都可以,但是规范用法是在启动类和配置类中添加注解。)

2)异步方法使用注解@Async的返回值只能为void或者Future。

3)异步方法不能使用static修饰

4)异步类没有使用 @Component 注解(或其他注解)导致spring无法扫描到异步类

5)异步方法不能与异步方法在同一个类中

6)类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象

7)在 @Async 方法上标注 @Transactional 是没用的。 在 @Async 方法调用的方法上标注@Transactional 有效。

8)调用被 @Async 标记的方法的调用者不能和被调用的方法在同一类中不然不会起作用!!!!!!!

9)使用 @Async 时是获取不到方法的返回值的,拿到的值为 null,如果返回的值是原始类型int、double、long等(不能为 null),就会报错。

在这里插入图片描述

整理完毕,完结撒花~ 🌻





参考地址:

1.@EnableAsync@Async基本使用方法,https://www.cnblogs.com/fzhblog/p/14012401.html

2.spring boot- @EnableAsync和@Async(Spring boot 注解@Async不生效 无效 不起作用),https://blog.csdn.net/inthat/article/details/111162059

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

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

相关文章

ArcGIS三体阴影(影像三维)显示马赛克?

我们经常基于ArcGIS通过DEM来做山体阴影 但是有时候你一放大就会出现很强的马赛克的效果 还有我们在利用ArcScene建三维场景 即使数据分辨率很高也会出现马赛克效果 那怎么来解决这个问题呢 让我们的山体阴影显示更加细腻 三维没有马赛克的效果呢&#xff1f; 右键图层选择如…

地铁站人流检测硬件部分

目录 一、概述 二、驱动程序 2.1debug串口 2.2体重传感器HX711 2.3滴答定时器 2.4ESP8266 2.5人体检测 2.6 IIC的GPIO 2.7 OLED的IIC 2.8 LED 三、应用 四、中断 一、概述 使用STM32C8T6作为主控 A9 ---> tx&#xff08;调试串口&#xff09; A10 ---> …

android framework-ActivityManagerService(AMS)下

一、ActivityThread \frameworks\base\core\java\android\app\ActivityThread.java 1.1、main public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// Install selective syscall interceptionAnd…

Hudi数据湖技术之核心概念

目录 1 基本概念1.1 时间轴Timeline1.2 文件管理1.3 索引Index 2 存储类型2.1 计算模型2.1.1 批式模型&#xff08;Batch&#xff09;2.1.2 流式模型&#xff08;Stream&#xff09;2.1.3 增量模型&#xff08;Incremental&#xff09; 2.2 查询类型&#xff08;Query Type&…

4.3调整基类成员在派生类中的访问属性的方法

同名成员 在定义派生类的时候&#xff0c;C语言允许派生类与基类中的函数名相同。如果在派生类中定义了与基类中相同的成员&#xff0c;则称派生类成员覆盖了基类的同名成员&#xff0c;在派生类中使用这个名字意味着访问在派生类中重新说明的成员。为了在派生类中使用基类的同…

C++ -4- 类和对象(下)

文章目录 1.初始化列表什么是初始化列表&#xff1f;初始化列表的 意义及使用 2.explicit关键字单参数构造函数&#xff08;C98&#xff09;多参数的构造函数&#xff08;C11&#xff09;&#xff08;了解&#xff09; 3.static静态成员静态成员变量与静态成员函数静态成员变量…

前端02:CSS选择器等基础知识

CSS基础选择器、设置字体样式、文本样式、CSS的三种引入方式、能使用Chrome调试工具调试样式 HTML专注做结构呈现&#xff0c;样式交给CSS&#xff0c;即结构&#xff08;HTML&#xff09;和样式CSS相分离 CSS主要由量分布构成&#xff0c;选择器以及一条或多条声明 选择器&…

18.Java泛型

目录 1. Java基本介绍 2. JDK下载安装及其环境配置 3. 一个简单的java程序 4. Eclipse基本使用、数据类型、运算符 5. 控制语句&#xff08;if、switch、for、while、foreach&#xff09; 6. Java数组 7. Java字符串对象(String|StringBuffer|StringBuilder|StringJoiner…

OFDM-LS信道估计 MMSE信道估计公式推导

假设ofdmN个子载波之间是完全正交的&#xff0c;即不考虑ICI影响&#xff0c;通过发送训练序列来实现信道估计。 其中&#xff0c;在推导6.8的时候&#xff0c;需要将6.6先拆解一下。 X − 1 Y X − 1 ( X H Z ) X − 1 X H X − 1 Z H X − 1 Z X^{-1}Y X^{-1}(XHZ)…

LeetCode213 打家劫舍 II 动态规划法

题目地址 https://leetcode.cn/problems/house-robber-ii/ 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 &#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装…

【Hive实战】探索Hive 2.X以及更早版本的MetaStore

探索Hive 2.X以及更早版本的MetaStore 文章目录 探索Hive 2.X以及更早版本的MetaStore概述配置元数据服务和元数据存储库基础配置参数其他配置参数默认配置配置元服务数据库使用内嵌模式的Derby库使用远程数据存储库 配置元数据服务本地/内嵌服务配置远程服务配置 元数据服务配…

【KingSCADA】什么是精灵图以及如何创建精灵图

大家好&#xff0c;我是雷工&#xff01; 本篇学习精灵图的制作&#xff0c;以下为学习内容及相关笔记。 一、什么是精灵图 精灵图是一种在外观上类似组合图&#xff0c;但内部嵌入了比较丰富的动画链接与逻辑控制&#xff0c;工程开发人员只要将其从精灵图库中调出来放置在开…

MySQL基础练习——创建数据库、数据表,并进行修改

目录 题目&#xff1a; 创建库和表&#xff1a; 创建库&#xff1a; 创建表&#xff1a; 将 c_contact 字段插入到 c_birth 字段后面&#xff1a; 将 c_name 字段数据类型改为VARCHAR(70)&#xff1a; 将 c_contact 字段改名为 c_phone&#xff1a; 将表名修改为 customer…

AD9208调试经验分享

背景概述 FMC137 是一款基于 VITA57.4 标准规范的 JESD204B 接口FMC 子 卡 模 块 &#xff0c; 该 模 块 可 以 实 现 4 路 14-bit 、 2GSPS/2.6GSPS/3GSPSADC 采集功能。该板卡 ADC 器件采用 ADI 公司的 AD9208 芯片&#xff0c;&#xff0c;与 ADI 公司的 AD9689 可以实现 …

量子力学 学习

对于同一个竖直向上量子比特&#xff0c;不对他进行任何的干扰&#xff0c;进行第一次水平测试实验会随机得到一个一或者负一&#xff0c;之后再进行多少次水平测试实验都与第一次的试验结果是相同的。 我们换用其他的竖直向上量子比特&#xff0c;或者对原来的量子比特进行干扰…

Matlab绘图中的一些技能

目录 1、matlab坐标轴设置多种字体(复合字体) 2、matlab图片中title生成的标题转移至图像下端 3、指定对应格式和期望dpi的图像进行保存、以及不留白保存 4、设置字体字号&#xff08;x、y轴&#xff0c;标题。全局字体等&#xff09; 5、设置刻度值信息&#xff0c;只有左…

引领文旅新体验!实时云渲染助力打造“永不落幕”的湾区文采会元宇宙

2022年11月25日至27日&#xff0c;2022年粤港澳大湾区公共文化和旅游产品&#xff08;东莞&#xff09;采购会&#xff08;简称“湾区文采会”&#xff09;在广东省东莞市文化馆举行。 文采会期间&#xff0c;文采会元宇宙线上虚拟展厅全新亮相&#xff0c;这艘承载着科技与文化…

5款十分小众的软件,知道的人不多但却很好用

今天推荐5款十分小众的软件&#xff0c;知道的人不多&#xff0c;但是每个都是非常非常好用的&#xff0c;有兴趣的小伙伴可以自行搜索下载。 1.视频直播录制——OBS Studio OBS Studio可以让你轻松地录制和直播你的屏幕、摄像头、游戏等内容。你可以使用OBS Studio来创建多种…

Mysql设置表只存储一段时间的数据

使用MySQL的事件调度器&#xff08;Event Scheduler&#xff09;来定期删除表中的数据。 假设你要删除的表是mytable&#xff0c;并且表中有一个名为created_at的日期时间类型的列&#xff0c;存储了每条记录的创建时间。你可以通过以下步骤设置表只存储30天的数据&#xff1a…

机器学习 协同过滤算法

协同过滤算法 协同过滤算法是根据已有的数据来推测出未知的数据&#xff0c;从海量的数据中找到相似度达到指定范围的数据&#xff0c;而这些数据成为你的邻居&#xff0c;系统将会为你推荐心仪的物品。 余弦相似法 通过计算两个向量的夹角余弦值来评估它们的相似度 修正余弦…