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

基于Spring 框架中的@Async 注解实现异步任务

@Async 是 Spring 框架中的一个注解,用于实现方法级别的异步执行。使用 @Async 可以让你的代码在非当前线程中执行,从而提高应用的并发性能。

1、 启用异步支持

在 Spring 应用的主配置类或任何其他配置类上添加 @EnableAsync 注解来开启异步任务的支持

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;@SpringBootApplication
@EnableAsync
public class Demo2024Application {public static void main(String[] args) {SpringApplication.run(Demo2024Application.class, args);}
}
2、配置异步执行器

默认情况下,Spring 使用一个内置的 SimpleAsyncTaskExecutor。为了更好地控制线程池,你可以自定义一个 ThreadPoolTaskExecutor 并在配置类中声明它。

   import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.AsyncConfigurer;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;@Configurationpublic class AppConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);  // 核心线程数executor.setMaxPoolSize(10);  // 最大线程数executor.setQueueCapacity(200);  // 队列大小executor.setThreadNamePrefix("MyExecutor-");  // 线程前缀名称executor.initialize();return executor;}}
3、标注异步方法

在需要异步执行的方法上添加 @Async 注解。这个方法将不会阻塞当前调用线程,而是立即返回,异步执行任务。

@Asyncpublic void testAsyncMethod(){log.info("执行Service类的异步方法 start .......");// 执行本Service 类的异步方法 sleep 10s 且每2秒输出一下进度try {for (int i = 0; i < 5; i++) {Thread.sleep(2000);log.info("执行Service类的异步方法 threadName:{}, progress .......:{}",Thread.currentThread().getName(),i);}} catch (InterruptedException e) {throw new RuntimeException(e);}log.info("执行Service类的异步方法 end .......");}
4、注意事项
  • a、异步方法不能直接在控制器(Controller)层使用,因为它们通常需要返回一个响应给客户端,这与异步方法的无返回行为不兼容
  • b、异步方法不能直接调用同一类中的其他异步方法,否则可能会导致死锁。
    通过测试发现,在同一类中调用其它异步方法,打印出来的线程名 都是同一个线程
    测试如下 在同一controller中
  /*** 测试本controller 类的异步方法*/@GetMapping("/testControllerAsync")public void testControllerAsync(){log.info("testControllerAsyncy,调用方法执行打印 开始 .......");log.info("testControllerAsync method threadName:{}",Thread.currentThread().getName());// 调用本controller 类的异步方法testCurrentControllerAsyncMethod();log.info("testControllerAsync,调用方法执行打印 开始 .......");}@Asyncpublic void testCurrentControllerAsyncMethod(){log.info("执行本controller 类的异步方法 start .......");// 执行本controller 类的异步方法 sleep 10s 且每2秒输出一下进度try {for (int i = 0; i < 5; i++) {Thread.sleep(2000);log.info("执行本controller 类的异步方法threadName:{}, progress .......:{}",Thread.currentThread().getName(),i);}} catch (InterruptedException e) {throw new RuntimeException(e);}log.info("执行本controller 类的异步方法 end .......");}

调用接口后 输出内容如下 可以看出 调用方法和被调用的异步方法 打印的threadName 是相同的,且调用方法的结束打印是在异步方法执行结束之后执行的,说明异步方法没生效
在这里插入图片描述
测试在同一service中

@Slf4j
@RestController
public class AsyncTestController {@Resourceprivate AsyncTestService asyncService;/*** 调用Service 类的方法,然后service再调用同service类中的异步方法*/@GetMapping("/testService")public void testService(){log.info("testService controller method 打印开始 .......");log.info("testService controller method threadName:{}",Thread.currentThread().getName());// 调用Service 类的方法,然后service再调用同service类中的异步方法asyncService.testServiceMethod();log.info("testService controller method 打印开始 .......");}
}@Service
@Slf4j
public class AsyncTestService {@Asyncpublic void testAsyncMethod(){log.info("执行Service类的异步方法 start .......");// 执行本Service 类的异步方法 sleep 10s 且每2秒输出一下进度try {for (int i = 0; i < 5; i++) {Thread.sleep(2000);log.info("执行Service类的异步方法 threadName:{}, progress .......:{}",Thread.currentThread().getName(),i);}} catch (InterruptedException e) {throw new RuntimeException(e);}log.info("执行Service类的异步方法 end .......");}public void testServiceMethod(){log.info("testServiceMethod method start .......");log.info("testServiceMethod method threadName:{}",Thread.currentThread().getName());// 调用Service正常方法,然后正常方法调用本service中的异步方法testAsyncMethod();log.info("testServiceMethod method end .......");}
}

调用接口后输出内容如下 可以看出 调用方法及service中的方法和被调用的异步方法 打印的threadName 是相同的,且调用方法的结束打印和service中调用的方法的打印是在异步方法执行结束之后执行的,说明异步方法没生效

在这里插入图片描述

5、 正确的调用 如下,
@Slf4j
@RestController
public class AsyncTestController {@Resourceprivate AsyncTestService asyncService;/*** 测试service 类的中异步方法*/@GetMapping("/testServiceAsync")public void testServiceAsync(){log.info("testServiceAsync controller method start .......");log.info("testServiceAsync controller method threadName:{}",Thread.currentThread().getName());// 调用Service 类的异步方法asyncService.testAsyncMethod();log.info("testServiceAsync controller method end .......");}}@Service
@Slf4j
public class AsyncTestService {@Asyncpublic void testAsyncMethod(){log.info("执行Service类的异步方法 start .......");// 执行本Service 类的异步方法 sleep 10s 且每2秒输出一下进度try {for (int i = 0; i < 5; i++) {Thread.sleep(2000);log.info("执行Service类的异步方法 threadName:{}, progress .......:{}",Thread.currentThread().getName(),i);}} catch (InterruptedException e) {throw new RuntimeException(e);}log.info("执行Service类的异步方法 end .......");}
}

调用后输出如下,可以看出 调用的controller方法 和service中异步方法打印的 线程名称是不相同的,且调用的controller方法的开始打印 及结整打印都是在异步方法打印之前执行的,说明异步方法生效了
在这里插入图片描述

相关文章:

  • Spring Aware接口:揭秘Bean生命周期中的“先知”角色与源码剖析
  • 第十三届蓝桥杯国赛大学B组填空题(c++)
  • window安装ffmpeg播放本地摄像头视频
  • Java面试进阶指南:高级知识点问答精粹(一)
  • Gitlab不允许使用ssh拉取代码的解决方案
  • 【NVM】持久内存的架构
  • vue3中element-plus下拉菜单与图标的使用
  • 22-LINUX--多线程and多进程TCP连接
  • 字节跳动(校招)算法原题
  • SQL生成序列浅析
  • Linux-用户管理
  • 【RabbitMQ】使用SpringAMQP的Publish/Subscribe(发布/订阅)
  • 【大模型部署】在C# Winform中使用文心一言ERNIE-3.5 4K 聊天模型
  • Hive环境搭建
  • 从 0 手撸一个 pytorch
  • ES2017异步函数现已正式可用
  • Javascript编码规范
  • Java多线程(4):使用线程池执行定时任务
  • Java面向对象及其三大特征
  • k个最大的数及变种小结
  • SpiderData 2019年2月13日 DApp数据排行榜
  • 从零开始的无人驾驶 1
  • 动态规划入门(以爬楼梯为例)
  • 构建二叉树进行数值数组的去重及优化
  • 巧用 TypeScript (一)
  • 设计模式走一遍---观察者模式
  • 数据结构java版之冒泡排序及优化
  • 我看到的前端
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 小程序 setData 学问多
  • 白色的风信子
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • linux 淘宝开源监控工具tsar
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • #{}和${}的区别是什么 -- java面试
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (12)Hive调优——count distinct去重优化
  • (Python) SOAP Web Service (HTTP POST)
  • (二)hibernate配置管理
  • (转)nsfocus-绿盟科技笔试题目
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET Core 中插件式开发实现
  • .NET Core引入性能分析引导优化
  • .Net IE10 _doPostBack 未定义
  • .Net Memory Profiler的使用举例
  • .NET 设计模式—适配器模式(Adapter Pattern)
  • .NET/C# 使窗口永不获得焦点
  • .Net中的集合
  • .NET中使用Protobuffer 实现序列化和反序列化
  • @serverendpoint注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [2009][note]构成理想导体超材料的有源THz欺骗表面等离子激元开关——
  • [AIGC] Java 和 Kotlin 的区别
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用