SpringBoot异步方法支持注解@Async应用

SpringBoot异步方法支持注解@Async应用
1.为什么需要异步方法?
合理使用异步方法可以有效的提高执行效率
同步执行(同在一个线程中):
异步执行(开启额外线程来执行):

2.SpringBoot中的异步方法支持
在SpringBoot中并不需要我们自己去创建维护线程或者线程池来异步的执行方法, SpringBoot已经提供了异步方法支持注解.
@EnableAsync // 使用异步方法时需要提前开启(在启动类上或配置类上)
@Async // 被async注解修饰的方法由SpringBoot默认线程池(SimpleAsyncTaskExecutor)执行
service层:
@Service
public class ArticleServiceImpl {// 查询文章public String selectArticle() {// 模拟文章查询操作System.out.println("查询任务线程"+Thread.currentThread().getName());return "文章详情";}// 文章阅读量+1@Asyncpublic void updateReadCount() {try {// 模拟耗时操作Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("更新任务线程"+Thread.currentThread().getName());}
}
controller层:
@RestController
public class AsyncTestController {@Autowiredprivate ArticleServiceImpl articleService;/*** 模拟获取文章后阅读量+1*/@GetMapping("/article")public String getArticle() {long start = System.currentTimeMillis();// 查询文章String article = articleService.selectArticle();// 阅读量+1articleService.updateReadCount();long end = System.currentTimeMillis();System.out.println("文章阅读业务执行完毕,执行共计耗时:"+(end-start));return article;}}
测试结果: 我们可以感受到接口响应速度大大提升, 而且从日志中key看到两个执行任务是在不同的线程中执行的
查询任务线程http-nio-8800-exec-3
文章阅读业务执行完毕,执行共计耗时:56
更新任务线程task-1
3.自定义线程池执行异步方法
SpringBoot为我们默认提供了线程池(SimpleAsyncTaskExecutor)来执行我们的异步方法, 我们也可以自定义自己的线程池.
第一步配置自定义线程池
@EnableAsync // 开启多线程, 项目启动时自动创建
@Configuration
public class AsyncConfig {@Bean("customExecutor")public ThreadPoolTaskExecutor asyncOperationExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// 设置核心线程数executor.setCorePoolSize(8);// 设置最大线程数executor.setMaxPoolSize(20);// 设置队列大小executor.setQueueCapacity(Integer.MAX_VALUE);// 设置线程活跃时间(秒)executor.setKeepAliveSeconds(60);// 设置线程名前缀+分组名称executor.setThreadNamePrefix("AsyncOperationThread-");executor.setThreadGroupName("AsyncOperationGroup");// 所有任务结束后关闭线程池executor.setWaitForTasksToCompleteOnShutdown(true);// 初始化executor.initialize();return executor;}
}
第二步, 在@Async注解上指定执行的线程池即可
// 文章阅读量+1
@Async("customExecutor")
public void updateReadCount() {// TODO 模拟耗时操作try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("更新文章阅读量线程"+Thread.currentThread().getName());
}
测试结果:
查询任务线程http-nio-8800-exec-1
文章阅读业务执行完毕,执行共计耗时:17
更新任务线程AsyncOperationThread-1
4.如何捕获(无返回值的)异步方法中的异常
以实现AsyncConfigurer接口的getAsyncExecutor方法和getAsyncUncaughtExceptionHandler方法改造配置类
自定义异常处理类CustomAsyncExceptionHandler
@EnableAsync // 开启多线程, 项目启动时自动创建
@Configuration
public class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// 设置核心线程数executor.setCorePoolSize(8);// 设置最大线程数executor.setMaxPoolSize(20);// 设置队列大小executor.setQueueCapacity(Integer.MAX_VALUE);// 设置线程活跃时间(秒)executor.setKeepAliveSeconds(60);// 设置线程名前缀+分组名称executor.setThreadNamePrefix("AsyncOperationThread-");executor.setThreadGroupName("AsyncOperationGroup");// 所有任务结束后关闭线程池executor.setWaitForTasksToCompleteOnShutdown(true);// 初始化executor.initialize();return executor;}@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return new CustomAsyncExceptionHandler();}
}
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {@Overridepublic void handleUncaughtException(Throwable throwable, Method method, Object... obj) {System.out.println("异常捕获---------------------------------");System.out.println("Exception message - " + throwable.getMessage());System.out.println("Method name - " + method.getName());for (Object param : obj) {System.out.println("Parameter value - " + param);}System.out.println("异常捕获---------------------------------");}}
测试结果:
查询任务线程http-nio-8800-exec-1
文章阅读业务执行完毕,执行共计耗时:20
异常捕获---------------------------------
Exception message - / by zero
Method name - updateReadCount
异常捕获---------------------------------
5.如何获取(有返回值)异步方法的返回值
使用Future类及其子类来接收异步方法返回值
注意:
- 无返回值的异步方法抛出异常不会影响Controller的主要业务逻辑
- 有返回值的异步方法抛出异常会影响Controller的主要业务逻辑
// 异步方法---------------------------------------------------------------------
@Async
public CompletableFuture<Integer> updateReadCountHasResult() {try {// 模拟耗时操作Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("更新文章阅读量线程"+Thread.currentThread().getName());return CompletableFuture.completedFuture(100 + 1);
}// Controller调用---------------------------------------------------------------------
@GetMapping("/article")
public String getArticle() throws ExecutionException, InterruptedException {// 查询文章String article = articleService.selectArticle();// 阅读量+1CompletableFuture<Integer> future = articleService.updateReadCountHasResult();int count = 0;// 循环等待异步请求结果while (true) {if(future.isCancelled()) {System.out.println("异步任务取消");break;}if (future.isDone()) {count = future.get();System.out.println(count);break;}}System.out.println("文章阅读业务执行完毕");return article + count;
}
6.常见失效场景
- 主启动类或者配置类没有添加@EnableAsync注解
- A方法调用被@Async注解修饰的B方法
@RestController
public class UserController {@Resourceprivate UserService userService;@RequestMapping("/getAll")public void getUsers(){System.out.println("业务开始");test();System.out.println("业务结束");}@Asyncpublic void test(){try {Thread.sleep(2000);System.out.println(Thread.currentThread().getName()+"查询到了所有的用户信息!");} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
- 被@Async注解修饰的方法必须不可以是static和private,必须为public
- 需要通过@Autowired或@Resource进行注入,不可手动new,基于SpringAOP实现
相关文章:
SpringBoot异步方法支持注解@Async应用
SpringBoot异步方法支持注解Async应用 1.为什么需要异步方法? 合理使用异步方法可以有效的提高执行效率 同步执行(同在一个线程中): 异步执行(开启额外线程来执行): 2.SpringBoot中的异步方法支持 在SpringBoot中并不需要我们自己去创建维护线程或者线程池来…...
UI/UX设计与前端开发:从零到一打造完美用户体验
引言 在当今的软件开发领域,UI/UX设计和前端开发是两个密不可分的环节。UI/UX设计师负责创造出直观、美观、用户友好的界面,而前端开发者则将这些设计转化为实际的、可交互的网页或应用。本文将深入探讨这两个领域的交集,并通过代码示例来展…...
Hadoop Hdfs基本命令
0目录 1.hadoop安装问题处理 2.hdfs基本命令 3.上传/下载文件和文件夹 1.hadoop安装问题处理 如果安装有进程无法启动,如下图 重新检查6个配置文件 Core-site.xml \ hdfs-site.xml \ hadoop-env.sh \ yarn-site.xml \ workers \ yarn-site.xml 来到hadoop313目录…...
Spring Boot 整合MyBatis(超详细)
😀前言 本篇博文关于Spring Boot 整合MyBatis,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,您的满意是我的动力&#x…...
【管理运筹学】第 6 章 | 运输问题(4,表上作业法 |闭回路调整法以及特殊情况 | 产销不平衡的运输问题)
文章目录 引言二、表上作业法2.3 改进的方法 —— 闭回路调整法2.4 表上作业法中的特殊情况(一)无穷多最优解(二)退化 三、产销不平衡的运输问题3.1 产量大于销量3.2 销量大于产量 写在最后 引言 接下来我们学习表上作业法的最后…...
Greenplum实用技巧
一、通过gp_segment_id查看数据倾斜 gp_segment_id是表中的隐藏列,用来标记该行属于哪个segment节点。因此可以基于该隐藏列进行分组查询,获取每个segment的记录数,从而判断表数据的分布是否均匀或有倾斜。 qb#select gp_segment_id, count…...
以物联网为核心的智慧工地云平台:聚集智能技术,实现建筑工地智慧管理
智慧工地云平台源码,智慧工地项目监管平台源码,智慧工地可视化数据大屏源码 智慧工地云平台是将云计算、大数据、物联网、移动技术和智能设备等信息化技术手段,聚集在建筑工地施工管理现场,围绕人员、机械、物料、环境等关键要素&…...
Java项目-苍穹外卖-Day05-Redis技术应用
1.店铺营业状态设置 需求分析和设计 左上角要求是有回显的 所以至少两个接口 1.查询营业状态接口(分为了管理端和用户端) 2.修改营业状态接口 因为管理端和用户端路径不同,所以现在是至少三个接口的 可以发现如果存到表里除了id只有一个…...
linux安装jmeter
linux安装jmeter 部署java1.8 下载jmeter安装包:官网、网盘5.6.2版本 # 解压 rootiZbp1at7nu2rpq4xn4zaf1Z:/opt/jmeter# sudo tar -xzf apache-jmeter-5.6.2.tgz # 加入环境变量 rootiZbp1at7nu2rpq4xn4zaf1Z:/opt/jmeter/apache-jmeter-5.6.2# export JMETER/op…...
【笔记】泛型以及如何绕过泛型定义
泛型定义以及其带来的好处 泛型使类型(类和接口)能够在定义类、接口和方法时成为参数。与方法声明中使用的更熟悉的形式参数非常相似,类型参数为您提供了一种通过不同输入重复使用相同代码的方法。区别在于形式参数的输入是值,而…...
JAVA JNA 调用C接口的三种方式
文章目录 1. 准备一个共享库文件2. JNA姿势1—继承Library接口3. JNA姿势2—直接NativeLibrary.getInstance3. JNA姿势3—Native方法 1. 准备一个共享库文件 test.c #include <stdio.h> int test(char *input){printf("input:%s\n",input);return 0; }libtes…...
StarRocks入门到熟悉
1、部署 1.1、注意事项 需要根据业务需求设计严谨的集群架构,一般来说,需要注意以下几项: 1.1.1、FE数量及高可用 FE的Follower要求为奇数个,且并不建议部署太多,通常我们推荐部署1个或3个Follower。在三个Followe…...
华为AR路由器 典型配置案例——以太网交换
目录 Eth-Trunk 例:配置三层链路聚合 组网需求 操作步骤 检查配置结果 配置脚本 VLAN 举例:配置基于接口划分VLAN,实现同一VLAN内的互通(同设备) 组网需求 操作步骤 检查配置结果 配置脚本 举例ÿ…...
DP读书:鲲鹏处理器 架构与编程(十三)操作系统内核与云基础软件
操作系统内核与云基础软件 鲲鹏软件构成硬件特定软件 鲲鹏软件构成硬件特定软件1. Boot Loader2. SBSA 与 SBBR3. UEFI4. ACPI 操作系统内核Linux系统调用Linux进程调度Linux内存管理Linux虚拟文件系统Linux网络子系统Linux进程间通信Linux可加载内核模块Linux设备驱动程序Linu…...
Vue2项目练手——通用后台管理项目第一节
Vue2项目练手——通用后台管理项目 知识补充yarn和npm区别npm的缺点:yarn的优点 npm查看镜像和设置镜像 项目介绍项目的技术栈 项目搭建文件目录 创建路由,引入element-uirouter/index.jsmain.jspages/Users.vuepages/Main.vuepages/Home.vuepages/Login…...
「Vue|网页开发|前端开发」02 从单页面到多页面网站:使用路由实现网站多个页面的展示和跳转
本文主要介绍如何使用路由控制来实现将一个单页面网站扩展成多页面网站,包括页面扩展的逻辑,vue的官方路由vue-router的基本用法以及扩展用法 文章目录 本系列前文传送门一、场景说明二、基本的页面扩展页面扩展是在扩什么创建新页面的代码,…...
【Nginx20】Nginx学习:FastCGI模块(二)缓存配置
Nginx学习:FastCGI模块(二)缓存配置 通过上篇文章的学习,普通的 PHP 与 Nginx 的连接就已经没啥大问题了。一般的网站直接那套配置就够了,这也是 Nginx 非常友好的一面。很多在默认的配置文件中注释掉的内容࿰…...
苹果支付外包开发流程
苹果支付的实现流程主要涉及集成苹果的支付系统——Apple Pay,以及在你的应用中处理支付交易。以下是一个简要的实现流程概述,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 1.开发者账号…...
银河麒麟V10(Tercel)服务器版安装 Docker
一、服务器环境 ## 查看系统版本,确认版本 cat /etc/kylin-release Kylin Linux Advanced Server release V10 (Tercel)## 操作系统 uname -p aarch64## 内核版本(≥ 3.10) uname -r 4.19.90-21.2.ky10.aarch64## iptables 版本(…...
web、HTTP协议
目录 一、Web基础 1.1 HTML概述 1.1.1 HTML的文件结构 1.2 HTML中的部分基本标签 1.3 URI 和 URL 二.HTTP协议 2.1.HTTP概念 2.2.HTTP协议版本 2.3.HTTP请求方法 2.4.HTTP请求访问的完整过程 2.5.HTTP状态码 2.6.HTTP请求报文和响应报文 2.7.HTTP连接优化 三.HTT…...
老设备重生:老旧MacBook Pro系统升级完全指南
老设备重生:老旧MacBook Pro系统升级完全指南 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 老旧硬件适配是延长设备生命周期的关键挑战,而开源解…...
文脉定序系统一键部署教程:基于Ubuntu 20.04的快速环境搭建
文脉定序系统一键部署教程:基于Ubuntu 20.04的快速环境搭建 你是不是也对那些能理解上下文、进行长文本对话的AI模型感到好奇?想自己动手部署一个来玩玩,但一看到复杂的安装步骤和满屏的命令行就头疼?别担心,今天我就…...
Face Analysis WebUI体验:智能人脸检测的简单方法
Face Analysis WebUI体验:智能人脸检测的简单方法 1. 开箱即用的人脸分析工具 你是否曾经需要快速分析一张照片中的人脸信息,却被复杂的安装步骤和命令行操作劝退?Face Analysis WebUI正是为解决这个问题而生。这个基于InsightFace模型的可…...
零基础玩转OpenClaw:nanobot镜像入门10个实用命令
零基础玩转OpenClaw:nanobot镜像入门10个实用命令 1. 认识nanobot镜像 第一次接触OpenClaw时,我被它"让AI直接操作电脑"的理念吸引,但本地部署的复杂环境配置让我望而却步。直到发现nanobot这个超轻量级镜像,内置了Qw…...
ENVI 5.3 vs 5.6 处理GF-6/GF-7数据实测:版本差异、流程对比与效率优化心得
ENVI 5.3与5.6处理GF-6/GF-7数据深度评测:从版本差异到实战优化 当高分卫星数据成为遥感分析的主流选择,ENVI作为行业标杆软件,其版本迭代对数据处理效率的影响往往被低估。本文将基于真实项目经验,拆解ENVI 5.3与5.6在处理GF-6/G…...
Java八股文实战:从cv_resnet101模型服务理解RPC与序列化
Java八股文实战:从cv_resnet101模型服务理解RPC与序列化 你是不是也遇到过这种情况?面试时被问到“RPC和HTTP有什么区别?”、“序列化协议怎么选?”,脑子里全是书本上的概念,什么“远程过程调用”、“轻量…...
RAG实战解析:如何通过检索增强生成提升知识密集型NLP任务性能
1. RAG技术为什么能改变知识密集型NLP任务格局 第一次听说RAG(Retrieval-Augmented Generation)这个概念时,我正被一个开放域问答项目折磨得焦头烂额。当时我们用纯BART模型生成的答案总是出现事实性错误,比如把"特斯拉创始人…...
Copilot 命令行使用方式介绍(npm)
1. 什么是 Apache SeaTunnel? Apache SeaTunnel 是一个非常易于使用、高性能、支持实时流式和离线批处理的海量数据集成平台。它的目标是解决常见的数据集成问题,如数据源多样性、同步场景复杂性以及资源消耗高的问题。 核心特性 丰富的数据源支持&#…...
TranslateGemma高可用部署:健康检查、监控与自动恢复策略
TranslateGemma高可用部署:健康检查、监控与自动恢复策略 1. 为什么高可用部署对TranslateGemma至关重要 TranslateGemma作为企业级神经机器翻译系统,在生产环境中面临着724小时不间断服务的严苛要求。不同于开发测试环境,生产部署必须考虑…...
AI芯片算力揭秘:从INT8到FP16,如何正确理解不同精度的TOPS值?
AI芯片算力揭秘:从INT8到FP16,如何正确理解不同精度的TOPS值? 当你在选购AI加速卡时,是否曾被厂商宣传的"200TOPS算力"搞得晕头转向?作为在边缘计算部署过数十个模型的工程师,我必须告诉你一个残…...
