SpringBoot【注解 01】@Scheduled实现定时任务的串行和并行执行
在SpringBoot中,如果使用@Scheduled注解来定义多个定时任务,默认情况下这些任务将会被安排在一个单线程的调度器中执行。这意味着,这些任务将会串行执行,而不是并行执行。当一个任务正在执行时,其他被触发的任务将会等待当前任务完成后再开始执行,这可能导致任务执行上的阻塞,特别是当某个任务执行时间较长时,可能会延迟后续任务的启动时间,影响定时任务的准时性。
@Scheduled
- 1.问题代码及测试结果
- 2.定时任务实现并行
- 2.1 使用自定义线程池(添加类)
- 2.2 使用异步处理(添加类和注解)
- 3.总结
1.问题代码及测试结果
问题代码:
@Scheduled(cron = "*/1 * * * * *")public void a() throws InterruptedException {log.info("A Start {}!", System.currentTimeMillis());Thread.sleep(2000);log.info("A End {}!", System.currentTimeMillis());}@Scheduled(cron = "*/1 * * * * *")public void b() {log.info("B Start {}!", System.currentTimeMillis());log.info("B End {}!", System.currentTimeMillis());}
部分测试结果:
15:38:29.001 [scheduling-1] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716968309001!
15:38:29.001 [scheduling-1] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716968309001!
15:38:29.001 [scheduling-1] INFO c.x.e.m.SchedulerTask - [a,44] - A Start 1716968309001!15:38:31.003 [scheduling-1] INFO c.x.e.m.SchedulerTask - [a,46] - A End 1716968311003!
15:38:31.003 [scheduling-1] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716968311003!
15:38:31.003 [scheduling-1] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716968311003!15:38:32.002 [scheduling-1] INFO c.x.e.m.SchedulerTask - [a,44] - A Start 1716968312002!15:38:34.003 [scheduling-1] INFO c.x.e.m.SchedulerTask - [a,46] - A End 1716968314003!
15:38:34.003 [scheduling-1] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716968314003!
15:38:34.003 [scheduling-1] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716968314003!
结果分析:
- A和B是串行的。
2.定时任务实现并行
2.1 使用自定义线程池(添加类)
可以通过配置一个自定义的TaskScheduler或者ThreadPoolTaskScheduler来为@Scheduled任务提供一个线程池,从而允许多个任务并行执行。例如,可以在配置类中定义一个ThreadPoolTaskScheduler Bean:
@Configuration
public class AsyncConfig {@Beanpublic ThreadPoolTaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();// 设置线程池大小scheduler.setPoolSize(10); scheduler.setThreadNamePrefix("my-scheduled-task-");return scheduler;}
}
并确保你的配置类被扫描到,且在@EnableScheduling注解的上下文中。
测试代码:
@Scheduled(cron = "*/1 * * * * *")public void a() throws InterruptedException {log.info("A Start {}!", System.currentTimeMillis());Thread.sleep(2000);log.info("A End {}!", System.currentTimeMillis());}@Scheduled(cron = "*/1 * * * * *")public void b() {log.info("B Start {}!", System.currentTimeMillis());log.info("B End {}!", System.currentTimeMillis());}
部分测试结果:
15:16:18.003 [my-scheduled-task-2] INFO c.x.e.m.SchedulerTask - [a,44] - A Start 1716966978003!
15:16:18.003 [my-scheduled-task-1] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716966978003!
15:16:18.003 [my-scheduled-task-1] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716966978003!15:16:19.002 [my-scheduled-task-1] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716966979002!
15:16:19.002 [my-scheduled-task-1] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716966979002!15:16:20.004 [my-scheduled-task-2] INFO c.x.e.m.SchedulerTask - [a,46] - A End 1716966980004!
15:16:20.004 [my-scheduled-task-3] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716966980004!
15:16:20.004 [my-scheduled-task-3] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716966980004!15:16:21.003 [my-scheduled-task-1] INFO c.x.e.m.SchedulerTask - [a,44] - A Start 1716966981003!
15:16:21.003 [my-scheduled-task-4] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716966981003!
15:16:21.003 [my-scheduled-task-4] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716966981003!15:16:22.001 [my-scheduled-task-2] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716966982001!
15:16:22.001 [my-scheduled-task-2] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716966982001!15:16:23.004 [my-scheduled-task-1] INFO c.x.e.m.SchedulerTask - [a,46] - A End 1716966983004!
15:16:23.004 [my-scheduled-task-3] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716966983004!
15:16:23.004 [my-scheduled-task-3] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716966983004!
结果分析:
- A和B是并行的;
- A和A或者B和B是串行的。
2.2 使用异步处理(添加类和注解)
结合@Async注解和@EnableAsync可以使得每个@Scheduled任务在独立的线程中异步执行。
首先需要在配置类中启用异步支持,并配置一个线程池,然后在每个定时任务方法上添加@Async注解。
@EnableAsync
@Configuration
public class AsyncConfig {@Beanpublic Executor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(200);executor.setThreadNamePrefix("Async-");executor.initialize();return executor;}
}
测试代码:
@Async@Scheduled(cron = "*/1 * * * * *")public void a() throws InterruptedException {log.info("A Start {}!", System.currentTimeMillis());Thread.sleep(2000);log.info("A End {}!", System.currentTimeMillis());}@Async@Scheduled(cron = "*/1 * * * * *")public void b() {log.info("B Start {}!", System.currentTimeMillis());log.info("B End {}!", System.currentTimeMillis());}
部分测试结果:
15:26:52.008 [Async-2] INFO c.x.e.m.SchedulerTask - [a,44] - A Start 1716967612008!
15:26:52.008 [Async-1] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716967612008!
15:26:52.009 [Async-1] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716967612009!15:26:53.002 [Async-4] INFO c.x.e.m.SchedulerTask - [a,44] - A Start 1716967613002!
15:26:53.002 [Async-3] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716967613002!
15:26:53.002 [Async-3] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716967613002!15:26:54.001 [Async-6] INFO c.x.e.m.SchedulerTask - [a,44] - A Start 1716967614001!
15:26:54.001 [Async-5] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716967614001!
15:26:54.001 [Async-5] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716967614001!
15:26:54.010 [Async-2] INFO c.x.e.m.SchedulerTask - [a,46] - A End 1716967614010!15:26:55.002 [Async-8] INFO c.x.e.m.SchedulerTask - [a,44] - A Start 1716967615002!
15:26:55.002 [Async-7] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716967615002!
15:26:55.002 [Async-7] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716967615002!
15:26:55.002 [Async-4] INFO c.x.e.m.SchedulerTask - [a,46] - A End 1716967615002!15:26:56.001 [Async-10] INFO c.x.e.m.SchedulerTask - [a,44] - A Start 1716967616001!
15:26:56.001 [Async-9] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716967616001!
15:26:56.001 [Async-9] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716967616001!
15:26:56.002 [Async-6] INFO c.x.e.m.SchedulerTask - [a,46] - A End 1716967616002!15:26:57.001 [Async-3] INFO c.x.e.m.SchedulerTask - [a,44] - A Start 1716967617001!
15:26:57.001 [Async-1] INFO c.x.e.m.SchedulerTask - [b,52] - B Start 1716967617001!
15:26:57.001 [Async-1] INFO c.x.e.m.SchedulerTask - [b,53] - B End 1716967617001!
15:26:57.002 [Async-8] INFO c.x.e.m.SchedulerTask - [a,46] - A End 1716967617002!
测试结果分析:
- A和B是并行的;
- A和A或者B和B也是并行的。
3.总结
如有错误,请小伙伴儿们不吝赐教。
定时任务有不同的需求,使用串行还是并行要结合业务进行选择。
相关文章:
SpringBoot【注解 01】@Scheduled实现定时任务的串行和并行执行
在SpringBoot中,如果使用Scheduled注解来定义多个定时任务,默认情况下这些任务将会被安排在一个单线程的调度器中执行。这意味着,这些任务将会串行执行,而不是并行执行。当一个任务正在执行时,其他被触发的任务将会等待…...
【工具】redis的安装使用
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Redis简介二、Redis的安装使用三、本文总结 前言 提示:这里可以添加本文要记录的大概内容: 随着开发语言及人工智能工具的普及&am…...
汇编:数据定义数据填充
数组的定义 在32位汇编语言中,定义数组时,通常使用定义数据指令(如 DB, DW, DD,DQ )和标签来指定数组的名称和内容。DB定义字节数组(每个元素占1字节)、DW定义字数组(每个元素占2字节ÿ…...
Python画图(多图展示在一个平面)
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
python-web应用程序-Django数据库-操作表中的数据
python-web应用程序-Django数据库-操作表中的数据 一、新增数据 类.objects.create(字段名 字段值,字段名 字段值,...)导入models包 models.User.objects.create(nameyulin,sex0,info三好学生)即可对数据进行操作 二、删除数据 类.objects.filter(…...
绕过WAF(Web应用程序防火墙)--介绍、主要功能、部署模式、分类及注入绕过方式等
网站WAF是一款集网站内容安全防护、网站资源保护及网站流量保护功能为一体的服务器工具。功能涵盖了网马/木马扫描、防SQL注入、防盗链、防CC攻击、网站流量实时监控、网站CPU监控、下载线程保护、IP黑白名单管理、网页防篡改功能等模块。能够为用户提供实时的网站安全防护&…...
11.7 堆排序
目录 11.7 堆排序 11.7.1 算法流程 11.7.2 算法特性 11.7 堆排序 Tip 阅读本节前,请确保已学完“堆“章节。 堆排序(heap sort)是一种基于堆数据结构实现的高效排序算法。我们可以利用已经学过的“建堆操作”和“元素出堆操作”…...
Patchwork++:基于点云的快速、稳健的地面分割方法
1. 背景 论文发表在2022IROS,是Patchwork的改进版本。算法通过数学方法进行快速而鲁棒性很强的地面分割,在智能机器人上的可操作性非常强。通过微调算法,可以应用于16-beams等多种规格的激光雷达。由于激光雷达点云数据标注的难度非常大&…...
Llama改进之——分组查询注意力
引言 今天介绍LLAMA2模型引入的关于注意力的改进——分组查询注意力(Grouped-query attention,GQA)1。 Transformer中的多头注意力在解码阶段来说是一个性能瓶颈。多查询注意力2通过共享单个key和value头,同时不减少query头来提升性能。多查询注意力可能导致质量下…...
英伟达开源新利器NV-Embed向量模型,基于双向注意力的LLM嵌入模型,MTEB 56项任务排名第一
前言 文本嵌入模型能够将文本信息转化为稠密的向量表示,并在信息检索、语义相似度计算、文本分类等众多自然语言处理任务中发挥着关键作用。近年来,基于解码器的大型语言模型 (LLM) 开始在通用文本嵌入任务中超越传统的 BERT 或 T5 嵌入模型,…...
JVM之【GC-垃圾清除算法】
Java虚拟机(JVM)中的垃圾收集算法主要分为以下几种: 标记-清除算法(Mark-Sweep)复制算法(Copying)标记-整理算法(Mark-Compact)分代收集算法(Generational C…...
数据分析每周挑战——心衰患者特征数据集
这是一篇关于医学数据的数据分析,但是这个数据集数据不是很多。 背景描述 本数据集包含了多个与心力衰竭相关的特征,用于分析和预测患者心力衰竭发作的风险。数据集涵盖了从40岁到95岁不等年龄的患者群体,提供了广泛的生理和生活方式指标&a…...
单例模式(Java实现)
我的相关文章: JavaSE 学习记录-CSDN博客 多线程笔记-CSDN博客 单例模式(Java实现)-CSDN博客 JUC笔记-CSDN博客 注解与反射(Java,类加载机制,双亲委派机制)-CSDN博客 1. 懒汉式线程不安全 pu…...
24.面向对象六大原则
目录介绍 00.面向对象六大原则01.代码单一职责原则02.代码开放封闭原则03.代码里氏替换原则04.代码依赖倒置原则05.代码接口隔离原则06.代码迪米特原则00.面向对象六大原则 六大原则一句话介绍 单一职责原则:指一个类的功能要单一,不能包罗万象。开放封闭原则:指一个模块在扩…...
Vue3-shallowRef与shallowReactive
shallowRef 作用:创建一个响应式数据,但只对顶层属性进行响应式处理。 用法: let myVar shallowRef(initialValue);特点:只跟踪引用值的变化,不关心值内部的属性变化。 shallowReactive 作用:创建一个浅…...
CI/CD(基于ESP-IDF)
主要参考资料 B站乐鑫信息科技《【乐鑫全球开发者大会】DevCon23 #15 |通过 CI/CD 进行流水线开发》 pytest-embedded乐鑫文档: https://docs.espressif.com/projects/pytest-embedded/en/latest/api.html 目录 CI/CD简介乐鑫内部CI/CD测试GitLab CI/CDGitHub Actio…...
聚观早报 | 东风奕派eπ008将上市;苹果Vision Pro发布会
聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 6月3日消息 东风奕派eπ008将上市 苹果Vision Pro发布会 特斯拉Model 3高性能版开售 小米14推送全新澎湃OS系统 …...
k8s牛客面经篇
k8s的pod版块: k8s的网络版块: k8s的deployment版块: k8s的service版块: k8s的探针板块: k8s的控制调度板块: k8s的日志监控板块: k8s的流量转发板块: k8s的宏观版块:...
第9周 基于MinIO与OSS实现分布式与云存储
第9周 基于MinIO与OSS实现分布式与云存储 1. 基于mybatis-plus数据修改非空属性忽略更新2. 文件上传3. 分布式文件存储3.1 文件存储架构演变4. Minio docker安装5. 文件服务整合minio依赖minio API测试yml配置minio信息minio配置类业务:上传文件6. 云存储阿里OSS:要钱6.1 依赖6…...
【Linux内核-编程指南】
■ IPC组件 添加链接描述 ■ ■ ■ ■ ■...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
