Spring Boot 中@Scheduled是单线程还是多线程?

在开发Spring Boot应用程序时,定时任务是一项常见的需求。Spring Boot提供了@Scheduled注解,可用于将方法标记为定时任务,并在预定的时间间隔内执行。那么@Scheduled注解的执行方式是单线程执行,还是多线程执行?@Scheduled注解的执行方式会不会产生线程不安全的问题?

以下总结@Scheduled注解的执行方式,并解释它在Spring Boot中的多线程行为。

一:案例演示

新建两个定时任务,一个是每2秒执行一次,一个是每3秒执行一次

@Component
public class ScheduledTest {@Scheduled(cron = "0/2 * * * * ? ")public void testTask1(){Thread thread = Thread.currentThread();String threadName = thread.getName();System.out.println(threadName+"-->"+ "testTask1-->"+LocalDateTime.now());}@Scheduled(cron = "0/3 * * * * ? ")public void testTask2(){Thread thread = Thread.currentThread();String threadName = thread.getName();System.out.println(threadName+"-->"+"testTask2-->"+ LocalDateTime.now());}
}

image-20240314003034203

发现这两个任务的线程是同一个,由此可以推测Spring Boot提供的@Scheduled注解默认是以单线程方式执行。下面看下源码:Scheduled提供的核心类ScheduledTaskRegistrar、ContextLifecycleScheduledTaskRegistrar

image-20240314003748775

ContextLifecycleScheduledTaskRegistrar 在bean实例化后会调 其父类ScheduledTaskRegistrar提供的scheduleTasks()方法,并且创建了单例的调度线程池

image-20240314003939023

image-20240314004104324

由此可见,Spring Boot提供的@Scheduled注解默认是以单线程方式执行。

有的人可能会想会不会是在同一个类中的方法导致结果是公用了同一个线程?不要猜,去验证!

image-20240314005121888

把testTask1和testTask2分别放在不同的类,结果共用同一个线程。

二:在单线程下会产生什么问题?

单线程环境下,如果某个任务处理时间很长,有可能导致其他任务阻塞。testTask1()休眠一小时模拟长时间处理任务,testTask2()一直处于阻塞状态。

@Component
public class ScheduledTest1 {@Scheduled(cron = "0/2 * * * * ? ")public void testTask1() throws InterruptedException {Thread thread = Thread.currentThread();String threadName = thread.getName();System.out.println("testTask1 开始执行~");TimeUnit.HOURS.sleep(1);System.out.println(threadName + "-->" + "testTask1-->" + LocalDateTime.now());}@Scheduled(cron = "0/3 * * * * ? ")public void testTask2() {Thread thread = Thread.currentThread();String threadName = thread.getName();System.out.println(threadName + "-->" + "testTask2-->" + LocalDateTime.now());}
}

image-20240314005903928

因此对于这种场景,我们可以考虑把@Scheduled配置成多线程环境下执行,解决@Scheduled在单线程环境下可能产生的问题。

三:@Scheduled支持多线程吗?

既然SchedulingConfigurer默认是创建了单例线程池,那我们是不是可以自定义线程池当做参数传给Scheduled呢?

@Configuration
public class ScheduleConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));}
}

案例验证代码

@Component
public class ScheduledTest6 {@Scheduled(cron = "0/2 * * * * ? ")public void testTask1() throws InterruptedException {Thread thread = Thread.currentThread();String threadName = thread.getName();System.out.println("testTask1 开始执行~");TimeUnit.HOURS.sleep(1);System.out.println(threadName + "-->" + "testTask1-->" + LocalDateTime.now());}@Scheduled(cron = "0/3 * * * * ? ")public void testTask2() {Thread thread = Thread.currentThread();String threadName = thread.getName();System.out.println(threadName + "-->" + "testTask2-->" + LocalDateTime.now());}
}

image-20240314011506586

由截图可知,有5个线程,1、2、5都正常处理testTask2任务,3、4两个线程正在处理testTask1()任务,因此多线程环境下可以解决单线程环境下可能导致的任务阻塞的问题。

更多细节可以关注我的个人主页 www.zhouy.work

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/539932.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谷歌通用AI智能体发布,3D游戏玩法要变天了

谷歌DeepMind号称打造出了首个能在广泛3D虚拟环境和视频游戏中遵循自然语言指令的通用AI智能体。 名为SIMA,不是NPC,是可以成为玩家拍档,帮忙干活打杂的那种。 比如,在《模拟山羊3》(Goat Simulator 3)中当…

Unload-labs

function checkFile() {var file document.getElementsByName(upload_file)[0].value;if (file null || file "") {alert("请选择要上传的文件!");return false;}//定义允许上传的文件类型var allow_ext ".jpg|.png|.gif";//提取上传文件的类…

C#,数值计算,数据测试用的对称正定矩阵(Symmetric Positive Definite Matrix)的随机生成算法与源代码

C.Hermite 1、对称矩阵 对称矩阵(Symmetric Matrices)是指以主对角线为对称轴,各元素对应相等的矩阵。在线性代数中,对称矩阵是一个方形矩阵,其转置矩阵和自身相等。1855年,埃米特(C.Hermite,1822-1901年)证明了别的数学家发现的一些矩阵类的特征根的特殊性质,如称为埃…

Elastic Agent 的安装及使用

概述 Elastic Agent是Elastic Stack中的一个全新组件,旨在简化和统一监控和集成管理流程。它是一个轻量级的代理,可以部署到各种不同类型的主机和容器中,用于收集系统指标、日志和事件数据,并将其发送到Elasticsearch进行存储和分…

知识蒸馏Matching logits与RocketQAv2

知识蒸馏Matching logits 公式推导 刚开始的怎么来,可以转看下面证明梯度等于输出值-标签y C是一个交叉熵,我们要求解的是这个交叉熵对的这个梯度。就是你可以理解成第个类别的得分。就是student model,被蒸馏的模型,它所输出的…

vue iview 级联选择器遇到的坑

我们PC项目用到的前端技术栈是vue+iview,最近有个需求,要做个级联选择器,并且是懒加载动态加载后端返回的数据。效果如下: 如下图所示,在我们封装的公共组件form-box.vue里有我们级联选择器: 代码如下: <!--级联选择器--><template v-else-if="item.type…

蓝桥杯 EDA 组 2021-2022 省赛真题+模拟题原理图解析

本文解析了标题内的原理图蓝桥杯EDA组真题&#xff0c;为方便阅读2023年真题/模拟和国赛部分放到其他章节解析。下文中重复或者是简单的电路节约篇幅不在赘述。 其中需要补充和计算原理图的题目解析都放在最下面 一、2021第十二届真题第一场 1.1 AMS1117 线性稳压器 最常见的1…

PyTorch搭建AlexNet训练集

本次项目是使用AlexNet实现5种花类的识别。 训练集搭建与LeNet大致代码差不多&#xff0c;但是也有许多新的内容和知识点。 1.导包&#xff0c;不必多说。 import torch import torch.nn as nn from torchvision import transforms, datasets, utils import matplotlib.pypl…

【STM32学习】基本定时器,输出比较模式,基本参数

1、概述 此项功能是用来控制一个输出波形&#xff0c;或者指示一段给定的的时间已经到时。 如输出PWM信号时&#xff0c;可用这个模式。 2、输出比较初始化函数&#xff0c;基本参数 以上函数是用来配置输出比较模块的&#xff0c;每个函数对应一个定时器的通道&#xff0c;配…

LVGL移植到ARM开发板(GEC6818开发板)

LVGL移植到ARM开发板&#xff08;GEC6818开发板&#xff09; 一、LVGL概述 LVGL&#xff08;Light and Versatile Graphics Library&#xff09;是一个开源的图形用户界面库&#xff0c;旨在提供轻量级、可移植、灵活和易于使用的图形用户界面解决方案。 它适用于嵌入式系统…

自然语言处理实验2 字符级RNN分类实验

实验2 字符级RNN分类实验 必做题&#xff1a; &#xff08;1&#xff09;数据准备&#xff1a;academy_titles.txt为“考硕考博”板块的帖子标题&#xff0c;job_titles.txt为“招聘信息”板块的帖子标题&#xff0c;将上述两个txt进行划分&#xff0c;其中训练集为70%&#xf…

概率论与数理统计(随机事件与概率)

1随机事件与概率 1.1随机事件及其运算规律 1.1.1运算 交换律结合律分配律德摩根律 1.2概率的定义及其确定方法 1.2.1概率的统计定义 频率 设在 n 次试验中&#xff0c;事件 A 发生了(A)次&#xff0c;则称为事件 A 发生的频率。 1.2.2概率的统计定义 在一组恒定不变的条…