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…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
