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

基于SpringBoot的任务管理三种方式

文章目录

  • 前言
  • 一,异步任务
    • 1.1 无返回值异步任务调用
    • 1.2 有返回值异步任务调用
  • 二、定时任务
    • 2.1 背景介绍
    • 2.2 todo
  • 三、邮箱任务
    • 3.1 todo

前言

开发 web 应用时,多数应用都具备任务调度功能,常见的任务包括异步任务、定时任务和邮件任务。我们以数据库报表为例看看任务调度如何帮助改善系统设计。报表可能是错综复杂的,用户可能需要很长时间找到需要的报表数据,此时我们可以在这个报表应用中添加异步任务减少用户等待时间,从而提高用户体验性;除此之外,还可以在报表应用中添加定时任务和邮件任务,以便用户可以安排在任何他们需要的时间定时生成报表,并在 Email 中发送。本文记录如何使用 SpringBoot 开发这些常见的任务。

一,异步任务

web 应用开发中,大多数情况都是通过同步方式完成数据交互处理,但是,当处理与第三方系统的交互时,容易造成响应迟缓的情况,之前大部分都是使用多线程完成此类任务,除此之外,还可以使用异步调用的方式完美解决这个问题。根据异步处理方式的不同,可以将异步任务的调用分为无返回值异步任务调用和有返回值异步任务调用。

1.1 无返回值异步任务调用

  1. 在启动类上添加注解 @EnableAsync(开启基于注解的异步任务支持)
  2. 在指定无返回值的业务方法上添加 @Asyn注解,实现异步请求方法

启动类

@EnableAsync
@SpringBootApplication
public class AsyncApplication {public static void main(String[] args) {SpringApplication.run(AsyncApplication.class, args);}
}

Service 层代码

@Service
public class AsyncService {@Asyncpublic void send(){System.out.println("调用短信验证码方法......");long start = System.currentTimeMillis();try {Thread.sleep(4000);} catch (InterruptedException e) {e.printStackTrace();System.out.println("出现异常:"+ e.getMessage());}long end = System.currentTimeMillis();System.out.println("短信验证码方法执行时间:"+(end - start) + "毫秒");}
}

Controller 层代码

@RestController
public class AsyncController {@Autowiredprivate AsyncService asyncService;@GetMapping("/async")public R testAsync(){long start = System.currentTimeMillis();asyncService.send();long end = System.currentTimeMillis();System.out.println("调用结束主流程耗时"+(end-start)+"毫秒");return R.ok().put("success", "调用结束主流程耗时"+(end-start)+"毫秒");}
}

若没有使用异步处理(注释掉 @Async 注解),访问接口返回数据如下

在这里插入图片描述

控制台输出内容:

在这里插入图片描述

若使用异步处理(使用 @Async 注解),访问接口返回数据如下

在这里插入图片描述

控制台输出内容:

在这里插入图片描述

当未使用异步处理时,访问接口需要等待4s左右才返回数据,而使用异步处理后几乎不需要等待时间,用户体验更佳了。

需要说明的是,无返回值异步方法在被主流程方法调用时,主流程方法不会阻塞,而是继续向下执行主流程方法内容,直接向页面响应结果,而调用的异步方法会作为一个子线程单独执行,直到异步方法执行完成。

1.2 有返回值异步任务调用

  1. 在启动类上添加注解 @EnableAsync(开启基于注解的异步任务支持)
  2. 在指定有返回值的业务方法上添加 @ASync注解,实现异步请求方法
    注意: 返回值必须用Future 泛型封装,例如: new AsyncResult(count),当想获取装的值时用 Futue 对象调用其 get() 方法即可获得。

业务场景设定:假设业务A(耗时3秒)进行数据分析返回一个整数值,业务B(耗时5秒)也进行数据分析返回一个整数值;且两者没有相互影响,计算业务A和业务B的返回整数值相加的结果。

同步方式: 先调用业务A ,再调用B,再将A返回值与B返回值相加,最终将结果返回给用户,总耗时肯定大于8秒。这种方式相对来说整体耗时更长,响应慢,降低了用户体验。

异步方式:

@Async
public Future<Integer> processA(){System.out.println("开始分析并统计业务A数据......");long start = System.currentTimeMillis();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();System.out.println("出现异常:"+ e.getMessage());}Integer numA = 20;long end = System.currentTimeMillis();System.out.println("业务A数据统计共耗时:"+(end - start));return new AsyncResult<Integer>(numA);
}@Async
public Future<Integer> processB(){System.out.println("开始分析并统计业务B数据......");long start = System.currentTimeMillis();try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();System.out.println("出现异常:"+ e.getMessage());}Integer numB = 25;long end = System.currentTimeMillis();System.out.println("业务B数据统计共耗时:"+(end - start));return new AsyncResult<Integer>(numB);
}
@GetMapping("/asyncTask")
public R Async() throws Exception {long start = System.currentTimeMillis();Future<Integer> processA = asyncService.processA();Future<Integer> processB = asyncService.processB();int sum = processA.get() + processB.get();//等待A B结果相加成功后再向下执行,这里阻塞了long end = System.currentTimeMillis();System.out.println("调用结束主流程耗时"+(end-start)+"毫秒");return R.ok().put("data","success");
}

响应结果:小于8秒,提升了系统响应速度

在这里插入图片描述
需要说明的是,有返回值异步方法在被主流程方法调用时,主流程方法是会短暂阻塞的,需要等待并获取异步方法的返回结果,而调用的两个异步方法会作为两个子线程并行执行,直到异步方法执行完成并返回结果,这样主流程会在最后一个异步方法返回结果后跳出阻塞状态。

二、定时任务

2.1 背景介绍

在实际开发中,可能会有这样一个需求,需要在每天的某个固定时间或者每隔一段时间让程序去执行某一个任务。例如,服务器数据定时在晚上零点备份。通常我们可以使用 scheduling Tasks 实现这一定时任务的处理;在时间定时任务时需要了解下几种和定时任务相关的注解,具体如下:

  1. @EnableScheduling 用于开启基于注解方式的定时任务支持,该注解主要用在项目启动类上。
  2. @scheduled 配置定时任务的执行规则,该注解主要用在定时业务方法上。

@scheduled 注解提供多个属性,精细化配置定时任务执行规则,这些属性及说明如下表:
todo

2.2 todo

三、邮箱任务

3.1 todo

相关文章:

基于SpringBoot的任务管理三种方式

文章目录前言一&#xff0c;异步任务1.1 无返回值异步任务调用1.2 有返回值异步任务调用二、定时任务2.1 背景介绍2.2 todo三、邮箱任务3.1 todo前言 开发 web 应用时&#xff0c;多数应用都具备任务调度功能&#xff0c;常见的任务包括异步任务、定时任务和邮件任务。我们以数…...

【华为OD机试模拟题】用 C++ 实现 - 查找单入口空闲区域(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明查找单入口空闲区域题目输入输出示例一输入输出说明示例二输入输出说明示例三输入输出说明示例...

普乐蛙部队vr训练设备军事训练vr体验馆设备元宇宙VR

案例一 地址&#xff1a;北京某部队 内置设备&#xff1a;乐享光轮、VR单车、暗黑战场、VR影院、游艺设备等 内容&#xff1a;部队增加VR体验设备&#xff0c;一、可以在强训练后&#xff0c;进行放松娱乐&#xff0c;也可以锻炼&#xff1b;二、VR设备可以模拟训练场景来进…...

大数据Hadoop教程-学习笔记05【Apache Hive DML语句与函数使用】

视频教程&#xff1a;哔哩哔哩网站&#xff1a;黑马大数据Hadoop入门视频教程 总时长&#xff1a;14:22:04教程资源: https://pan.baidu.com/s/1WYgyI3KgbzKzFD639lA-_g 提取码: 6666【P001-P017】大数据Hadoop教程-学习笔记01【大数据导论与Linux基础】【17p】【P018-P037】大…...

Unity动画转Three.js动画

一&#xff1a;应用场景 在工作中&#xff0c;由于算法给到的动画文件是Unity的.anim格式动画文件&#xff0c;这个格式不能直接在Web端用Three.js引擎运行。因此需要将.anim格式的动画文件转换为Three.js的AnimationClip动画对象。 二&#xff1a;.ANIM格式与AnimationClip对…...

07_MySQL的单行函数

1. 函数的理解1.1 什么是函数函数在计算机语言的使用中贯穿始终&#xff0c;函数的作用是什么呢&#xff1f;它可以把我们经常使用的代码封装起来&#xff0c;需要的时候直接调用即可。这样既提高了代码效率 &#xff0c;又提高了可维护性 。在 SQL 中我们也可以使用函数对检索…...

QML 第一个应用程序Window

1.创建QML工程 新建文件或者项目-->选择Qt Quick Application 然后生成了一个默认的Window 2.main.cpp中如何加载的qml文件 QQmlApplicationEngine提供了从单个QML文件加载应用程序的便捷方式。 此类结合了QQmlEngine和QQmlComponent&#xff0c;以提供一种方便的方式加载…...

RedisAI编译安装(一)

1.概述 RedisAI 是一个 Redis 模块&#xff0c;用于执行深度学习/机器学习模型并管理其数据。它的目的是成为模型服务的“主力”&#xff0c;通过为流行的 DL/ML 框架和无与伦比的性能提供开箱即用的支持。RedisAI 遵循数据局部性原则&#xff0c;最大限度地提高计算吞吐量并减…...

换掉 Maven,我就用Gradle,急速编译

相信使用Java的同学都用过Maven&#xff0c;这是一个非常经典好用的项目构建工具。但是如果你经常使用Maven&#xff0c;可能会发现Maven有一些地方用的让人不太舒服&#xff1a; Maven的配置文件是XML格式的&#xff0c;假如你的项目依赖的包比较多&#xff0c;那么XML文件就…...

22.2.26打卡 Codeforces Round #853 (Div. 2)

A题极端考虑, 只要存在一个前缀数组的最大公约数小于等于2, 将其放在数组最前端, 那么保证能够满足题目要求数据范围这么小, 果断暴力Serval and Mochas Array题目描述Mocha likes arrays, and Serval gave her an array consisting of positive integers as a gift.Mocha thin…...

结构体字节对齐、偏移量

复习下struct的大小、成员偏移量offsetof&#xff0c;说下我的理解&#xff1a; 64位下默认对齐数default8原则1&#xff1a;struct中每一个成员变量tmp的对齐数realmin{default,tmp} struct Student {int num;//0char name[8];double score; } stu; 这个结构体stu中&#x…...

全网最全——Java 数据类型

一、数据类型方法论 程序本质上是对数据的处理&#xff08;逻辑运算&#xff09;&#xff0c;因此任何语言都需先解决如何表征【数据】这个核心概念。数据作为抽象的概念&#xff0c;天然的包含2个方面属性&#xff1a; 类型&#xff1a;类型决定了数据只能和同类型的数据进行…...

数据结构基础之动态数组

目录 前言 1、Java中的数组 2、实现动态数组 2.1、基本类结构设计 2.2、添加元素 2.3、查询&修改元素 2.4、包含&搜索&删除 2.5、数组扩容 前言 今天我们来学习一下关于数据结构的一些基础知识&#xff0c;数据结构研究的是数据如何在计算机中进行组织和存…...

【跟我一起读《视觉惯性SLAM理论与源码解析》】第九章 地图点、关键帧以及图结构

这一章主要讲了一些基本内容&#xff0c;包括ORB-SLAM2中地图点&#xff0c;关键帧图结构的问题 地图点和特征点的关系&#xff1f;有时候地图点对应不同帧上的特征点&#xff0c;特征点可以通过三角化得到地图点地图点的几个属性&#xff0c;平均观测方向&#xff0c;以及观测…...

网络安全——数据链路层安全协议(2)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.局域网数据链路层安全协议 1.IEEE 802.10 &#xff08;1&#xff09;IEE…...

【华为OD机试模拟题】用 C++ 实现 - 热点网络统计(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明热点网络统计【华为OD机试模拟题】题目输入输出描述示例一输入输出示例二输入输出Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出…...

人工智能学习07--pytorch09--LeNet

参考&#xff1a; 视频&#xff1a; https://www.bilibili.com/video/BV187411T7Ye/?spm_id_from333.999.0.0&vd_sourceb425cf6a88c74ab02b3939ca66be1c0d 博客&#xff1a;https://blog.csdn.net/STATEABC/article/details/123661612?utm_mediumdistribute.pc_feed_404.…...

java泛型编程初识

java泛型编程初识1.泛型解决的是什么问题2.泛型实例化语句3.自定义泛型1)自定义泛型类或接口2)自定义泛型方法4.泛型使用中的继承和通配1)通配2)继承使用限制1.泛型解决的是什么问题 很多类、接口、方法中逻辑相同&#xff0c;只是操作的对象类型不同&#xff0c;这个时候就可…...

代码随想录算法训练营 || 贪心算法 1005 134 135

Day291005.K次取反后最大化的数组和力扣题目链接给定一个整数数组 A&#xff0c;我们只能用以下方法修改该数组&#xff1a;我们选择某个索引 i 并将 A[i] 替换为 -A[i]&#xff0c;然后总共重复这个过程 K 次。&#xff08;我们可以多次选择同一个索引 i。&#xff09;以这种方…...

Spring框架面试题

springboot的自动装配原理 主类上的SpringBootApplication存在EnableAutoConfiguration&#xff0c;EnableAutoConfiguration会导入AutoConfigurationImportSelector组件&#xff0c;其AutoConfigurationImportSelector$AutoConfigurationGroup#process()方法会读取当前应用所有…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...