【SpringBoot】实现Async异步任务
1. 环境准备
在 Spring Boot 入口类上配置 @EnableAsync 注解开启异步处理。
创建任务抽象类 AbstractTask,并分别配置三个任务方法 doTaskOne(),doTaskTwo(),doTaskThree()。
public abstract class AbstractTask {private static Random random = new Random();public void doTaskOne() throws Exception {System.out.println("开始做任务一");long start = currentTimeMillis();sleep(random.nextInt(10000));long end = currentTimeMillis();System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");}public void doTaskTwo() throws Exception {System.out.println("开始做任务二");long start = currentTimeMillis();sleep(random.nextInt(10000));long end = currentTimeMillis();System.out.println("完成任务二,耗时:" + (end - start) + "毫秒");}public void doTaskThree() throws Exception {System.out.println("开始做任务三");long start = currentTimeMillis();sleep(random.nextInt(10000));long end = currentTimeMillis();System.out.println("完成任务三,耗时:" + (end - start) + "毫秒");}
}
2. 同步调用
下面通过一个简单示例来直观的理解什么是同步调用:
- 定义
Task类,继承AbstractTask,三个处理函数分别模拟三个执行任务的操作,操作消耗时间随机取(10秒内)。
@Component
public class SyncTask extends AbstractTask {
}
- 在 单元测试 用例中,注入
SyncTask对象,并在测试用例中执行doTaskOne(),doTaskTwo(),doTaskThree()三个方法。
@RunWith(SpringRunner.class)
@SpringBootTest
public class TaskTest {@Autowiredprivate SyncTask task;@Testpublic void testSyncTasks() throws Exception {task.doTaskOne();task.doTaskTwo();task.doTaskThree();}
}
- 执行单元测试,可以看到类似如下输出:
开始做任务一
完成任务一,耗时:6720毫秒
开始做任务二
完成任务二,耗时:6604毫秒
开始做任务三
完成任务三,耗时:9448毫秒
任务一、任务二、任务三顺序的执行完了,换言之 doTaskOne(),doTaskTwo(),doTaskThree() 三个方法顺序的执行完成。
3. 异步调用
上述的 同步调用 虽然顺利的执行完了三个任务,但是可以看到 执行时间比较长,若这三个任务本身之间 不存在依赖关系,可以 并发执行 的话,同步调用在 执行效率 方面就比较差,可以考虑通过 异步调用 的方式来 并发执行。
- 创建
AsyncTask类,分别在方法上配置@Async注解,将原来的 同步方法 变为 异步方法。
@Component
public class AsyncTask extends AbstractTask {@Asyncpublic void doTaskOne() throws Exception {super.doTaskOne();}@Asyncpublic void doTaskTwo() throws Exception {super.doTaskTwo();}@Asyncpublic void doTaskThree() throws Exception {super.doTaskThree();}
}
- 在 单元测试 用例中,注入
AsyncTask对象,并在测试用例中执行doTaskOne(),doTaskTwo(),doTaskThree()三个方法。
@Autowired
private AsyncTask asyncTask;@Test
public void testAsyncTasks() throws Exception {asyncTask.doTaskOne();asyncTask.doTaskTwo();asyncTask.doTaskThree();
}
- 执行单元测试,可以看到类似如下输出:
开始做任务三
开始做任务一
开始做任务二
如果反复执行单元测试,可能会遇到各种不同的结果,比如:
- 没有任何任务相关的输出
- 有部分任务相关的输出
- 乱序的任务相关的输出
原因是目前 doTaskOne(),doTaskTwo(),doTaskThree() 这三个方法已经 异步执行 了。主程序在 异步调用 之后,主程序并不会理会这三个函数是否执行完成了,由于没有其他需要执行的内容,所以程序就 自动结束 了,导致了 不完整 或是 没有输出任务 相关内容的情况。
注意:@Async所修饰的函数不要定义为static类型,这样异步调用不会生效。
4. 异步回调
为了让 doTaskOne(),doTaskTwo(),doTaskThree() 能正常结束,假设我们需要统计一下三个任务 并发执行 共耗时多少,这就需要等到上述三个函数都完成动用之后记录时间,并计算结果。
那么我们如何判断上述三个 异步调用 是否已经执行完成呢?我们需要使用 Future 来返回 异步调用 的 结果。
- 创建
AsyncCallBackTask类,声明doTaskOneCallback(),doTaskTwoCallback(),doTaskThreeCallback()三个方法,对原有的三个方法进行包装。
@Component
public class AsyncCallBackTask extends AbstractTask {@Asyncpublic Future<String> doTaskOneCallback() throws Exception {super.doTaskOne();return new AsyncResult<>("任务一完成");}@Asyncpublic Future<String> doTaskTwoCallback() throws Exception {super.doTaskTwo();return new AsyncResult<>("任务二完成");}@Asyncpublic Future<String> doTaskThreeCallback() throws Exception {super.doTaskThree();return new AsyncResult<>("任务三完成");}
}
- 在 单元测试 用例中,注入
AsyncCallBackTask对象,并在测试用例中执行doTaskOneCallback(),doTaskTwoCallback(),doTaskThreeCallback()三个方法。循环调用Future的isDone()方法等待三个 并发任务 执行完成,记录最终执行时间。
@Autowired
private AsyncCallBackTask asyncCallBackTask;@Test
public void testAsyncCallbackTask() throws Exception {long start = currentTimeMillis();Future<String> task1 = asyncCallBackTask.doTaskOneCallback();Future<String> task2 = asyncCallBackTask.doTaskTwoCallback();Future<String> task3 = asyncCallBackTask.doTaskThreeCallback();// 三个任务都调用完成,退出循环等待while (!task1.isDone() || !task2.isDone() || !task3.isDone()) {sleep(1000);}long end = currentTimeMillis();System.out.println("任务全部完成,总耗时:" + (end - start) + "毫秒");
}
看看都做了哪些改变:
- 在测试用例一开始记录开始时间;
- 在调用三个异步函数的时候,返回Future类型的结果对象;
- 在调用完三个异步函数之后,开启一个循环,根据返回的Future对象来判断三个异步函数是否都结束了。若都结束,就结束循环;若没有都结束,就等1秒后再判断。
- 跳出循环之后,根据结束时间 - 开始时间,计算出三个任务并发执行的总耗时。
执行一下上述的单元测试,可以看到如下结果:
开始做任务三
开始做任务一
开始做任务二
完成任务二,耗时:2572毫秒
完成任务一,耗时:7333毫秒
完成任务三,耗时:7647毫秒
任务全部完成,总耗时:8013毫秒
可以看到,通过 异步调用,让任务一、任务二、任务三 并发执行,有效的 减少 了程序的 运行总时间。
相关文章:
【SpringBoot】实现Async异步任务
1. 环境准备 在 Spring Boot 入口类上配置 EnableAsync 注解开启异步处理。 创建任务抽象类 AbstractTask,并分别配置三个任务方法 doTaskOne(),doTaskTwo(),doTaskThree()。 public abstract class AbstractTask {private static Random r…...
Node =>Express学习
1.Express 能做什么 能快速构建web网站的服务器 或 Api接口的服务期 Web网站服务器,专门对外提供Web网页资源的服务器Api接口服务器:专门对外提供API接口的服务器 2.安装 在项目所处的目录中,运行以下命令,简装到项目中了 npm …...
QT基础入门【布局篇】消除控件之间的间隔
一、相关参数 layoutLeftMargin: layout内的布局距离边框左端的距离。 layoutTopMargin: layout内的布局距离边框顶端的距离。 layoutRightMargin: layout内的布局距离边框右端的距离。 layoutBottomMargin: layout内的布局距离边框底端的距离。 layoutHorizontalSpacing: layo…...
vue脚手架 element-ui spring boot 实现图片上传阿里云 并保存到数据库
一.阿里云 注册登陆就不讲了,登陆进去后如下操作 1. 进入对象存储OSS 创建一个新的Bucket 随后点击新建的bucket 2.去访问RAM 前往RAM控制台 3.去创建用户 4.创建密匙 5.随后返回RAM控制台 给用户增加权限,文件上传所需权限,需要带含有…...
【FPGA】Verilog:组合电路 | 3—8译码器 | 编码器 | 74LS148
前言:本章内容主要是演示Vivado下利用Verilog语言进行电路设计、仿真、综合和下载 示例:编码/译码器的应用 功能特性: 采用 Xilinx Artix-7 XC7A35T芯片 配置方式:USB-JTAG/SPI Flash 高达100MHz 的内部时钟速度 存储器&…...
GLP-1类药物研发进展-销售数据-上市药品前景分析
据一项2021 年的报告发现,当 GLP-1 类似物用于治疗 2 型糖尿病时,全因死亡率降低了 12%,它们不仅降糖效果显著,同时还兼具减重、降压、改善血脂谱等作用。近几年,随着GLP-1R激动剂类药物市场规模不断增长,美…...
C++远程监控系统接收端- RevPlayMDIChildWnd.cpp
void CRevPlayWnd::InitMultiSock() { int RevBuf; int status; BOOL bFlag; CString ErrMsg; SOCKADDR_IN stLocalAddr; SOCKADDR_IN stDestAddr; SOCKET hNewSock; int RevLensizeof(RevBuf); //创建一个IP组播套接字 MultiSock W…...
QT之OpenGL深度测试
QT之OpenGL深度测试1. 深度测试概述1. 1 提前深度测试1.2 深度测试相关函数2. 深度测试精度2.1 深度冲突3. Demo4. 参考1. 深度测试概述 在OpenGL中深度测试(Depth Testing)是关闭的,此时在渲染图形时会产生一种现象后渲染的会把最先渲染的遮挡住。而在启用深度测试…...
用LCR测试仪测试无线充电系统中的线圈
宽阻抗范围用来表征电感和质量因数– 高精度 DCR 测量– 制造环节快速测量– 大量夹具可供选择智能终端上不断增加新功能,电池寿命成为用户最头痛的问题之一。相比便携式电源和电缆供电而言,无线充电技术因其方便性和多功能性获得了很大的关注࿰…...
华为、南卡和漫步者蓝牙耳机怎么选?国产高性价比蓝牙耳机推荐
随着蓝牙耳机的快速发展,现如今使用蓝牙耳机的人也越来越多。其中,日益增多的国产蓝牙耳机品牌也逐渐被大众认识、认可。目前一些热销的国产蓝牙耳机,如华为、南卡和漫步者等都是大家比较熟知的品牌。那么,这三个品牌哪个性价比高…...
MySQl学习(从入门到精通12)
MySQl学习(从入门到精通12)第 15 章_存储过程与函数1. 存储过程概述1. 1 理解1. 2 分类2. 创建存储过程2. 1 语法分析2. 2 代码举例3. 调用存储过程3. 1 调用格式3. 2 代码举例3. 3 如何调试4. 存储函数的使用4. 1 语法分析4. 2 调用存储函数4. 3 代码举…...
08讲 | 基于STM32单片机NBIOT定位实战项目
前言 绘制基于 STM32 单片机的 NBIOT 实战开发板。 文章目录前言一、原理图1、绘制1)电源供电a、USB 转 TTL 电路b、锂电池充电管理电路c、3.3V电压转换电路d、一键开关机电路2)单片机最小系统3)ADC电压转换电路4)NBIOT 模组串口电…...
提取接近竖直物体(粗定位)
由于项目的需要提取图像之中的一个接近于竖直的物体,一般的方法是进行图像分割,分割方式使用什么OTSU方式以及hsv方法等等。但是项目中使用的相机是黑白相机,会受到一定的限制。因此想到的是使用线条提取方式。线条提取方式之中最好的方法是使…...
程序环境和预处理
目录一、程序的翻译环境和执行环境二、编译链接2.1 翻译环境2.2 编译2.2.1 预处理2.2.2 编译2.2.3 汇编2.3 链接2.4 结果三、运行环境四、预处理详解4.1 #define4.1.1 #define定义标识符4.1.2 #define定义宏4.1.3 #define 替换规则4.1.4 #和##4.1.5 带副作用的宏参数4.1.6 宏和…...
财报解读:业务复苏迹象明显,中国中免能否重写增长神话?
2月3日,中国中免披露2022年度业绩快报,2022年总营收为544.63亿元,同比下降19.52%;实现归属于上市公司股东的净利润50.25亿元,同比下降47.95%。来源:中国中免2022年度业绩快报业绩近乎腰斩,但从长…...
macOS中虚拟机桥接模式分配静态ip
1.首先使用dhclient命令,在局域网中分配一个C类地址。 2.获得地址后,输入ifconfig,查看分配的地址。 3.然后编辑vi /etc/sysconfig/network-scripts/ifcfg-en***文件 在该配置文件中编辑,设置ONBOOTyes,而后添加静态配…...
prometheus increase函数统计得到小数
今天发现prometheus的increase函数得到了小数,研究一下源码,以下是rate/increase/delta 对应的计算函数https://github.com/prometheus/prometheus/blob/d77b56e88e3d554a499e22d2073812b59191256c/promql/functions.go#L55// extrapolatedRate is a uti…...
C++学习记录——유 类和对象(3)
文章目录1、赋值运算符重载1、运算符重载1、理解2、运算符重载实例2、赋值运算符重载2、日期类的实现1、加减函数1、加函数2、减函数2、前/后置--重载3.两个日期相减其他1、流插入2、流提取日期类的整体实现代码: https://gitee.com/kongqizyd/start-some-c-codes-for-learning…...
基于Hi3861平台的OpenHarmony程序是如何启动运行的
一、前言 在继续后面课程的内容讲解前,我们要知道在H3861平台上编写的代码到底是如何启动的,这一点很重要。 先分析HelloWorld程序的启动运行流程,并顺便讲解OpenHarmony在H3861平台的,系统是从哪里启动的。 反着推导函数之间具体…...
2023彻底解决Typora使用iPic微博图床失效问题
一、问题描述用Typora搭配iPic图床使用,最近csdn图片显示不出来用浏览器打开图片显示403,这里原因是微博图床出问题了导致的而使用iPic其他图床则需要一直付费,那有没有一劳永逸的解决所有问题呢?二、旧图恢复首先怎么找回旧图&am…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
