IDEA SpringBoot实现定时任务(保姆级教程,超详细!!!)

目录

1. 前言

2. 创建SpringBoot项目

3. Maven依赖引入 

4. 创建定时任务

5. 问题:执行时间延迟和单线程执行

5.1 问题原因 

5.2 解决方式


1. 前言

在现代化应用中,定时任务(Scheduled Tasks)是不可或缺的一部分,它们允许开发者在预定的时间间隔内自动执行特定任务,如数据同步、报告生成、系统维护等。Spring Boot作为一款流行的Java开发框架,提供了简洁而强大的定时任务实现方式。

Spring Boot通过内置的@Scheduled注解和@EnableScheduling配置,使得开发者能够轻松地在应用中集成定时任务功能。无需引入额外的依赖或复杂的配置,只需在方法上添加@Scheduled注解,并指定任务的执行计划,Spring Boot便会自动处理任务的调度和执行。

本教程将带您逐步了解Spring Boot定时任务的实现过程,包括基本的配置和注解使用、常见的执行计划设置、以及高级功能如动态定时任务、多线程定时任务等。通过本教程的学习,您将能够掌握在Spring Boot中高效实现定时任务的方法和技巧,为您的应用增添更多自动化和智能化的功能。

请注意,随着技术的不断发展,Spring Boot的版本和特性也在不断更新。因此,建议参考最新的Spring Boot官方文档和相关教程来获取最准确的信息。同时,本教程也提供了实用的示例和代码,帮助您更好地理解和应用定时任务功能。

2. 创建SpringBoot项目

首先,我们需要创建SpringBoot项目。在创建SpringBoot项目时,可以选择使用Spring Initializr来快速生成项目结构。

创建SpringBoot项目教程,本文就不过多讲解了,具体操作可参考往期博文:

IDEA创建SpringBoot项目教程,讲解超详细(2024最新)!!!

3. Maven依赖引入 

在Spring Boot项目中使用@Scheduled注解实现定时任务时,你通常不需要额外导入特定的依赖,因为@Scheduled是Spring框架的核心功能之一,并且Spring Boot会自动配置与调度相关的组件。

但是,确保你的Spring Boot项目包含了Spring Boot的起步依赖(starter dependencies),特别是spring-boot-starter或与你项目相关的特定starter依赖(比如spring-boot-starter-web用于Web应用),这些starter依赖会包含使用@Scheduled所需的所有必要组件。

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

4. 创建定时任务

@Slf4j
@Component
@EnableScheduling
public class DemoTask {// 每10秒执行一次,cron的表达式暂时不多说明了,可以自行百度学习@Scheduled(cron = "0/10 * * * * ? ")public void testSchedule() {log.info("当前执行任务的线程号ID===>{}", Thread.currentThread().getId()); // 日志输出}}

注释讲解

 @Slf4j:Lombok库提供的一个注解,用于在Java类中自动生成一个名为log的日志对象。通过使用@Slf4j注解,你可以直接在代码中调用log对象的方法来记录不同级别的日志,如log.info(), log.debug(), log.error() 等。这些日志方法可以帮助你记录应用程序的运行状态、调试信息、警告和错误等,从而有助于排查问题、跟踪程序运行情况,提高系统稳定性和可维护性。

@Component:Spring框架中的一个核心注解,它用于将一个类标记为Spring上下文中的一个组件。当一个类被标记为@Component时,Spring容器会在启动时自动扫描并实例化这个类,并将其注册到Spring上下文中。这个类就成为了Spring上下文中的一个bean,可以被其他bean通过依赖注入的方式使用。

@EnableScheduling:Spring框架提供的一个注解,用于启用基于注解的定时任务调度功能。当在Spring的配置类(如使用@Configuration注解的类)上使用@EnableScheduling注解时,Spring会自动配置一个任务调度器(TaskScheduler),负责管理所有带有@Scheduled注解的方法。

@Scheduled:Spring框架中用于定时任务调度的注解。它允许开发者将一个方法标记为定时任务,并配置任务的执行时间间隔或Cron表达式,从而实现在指定时间或按照指定周期自动执行该方法的功能。 除了配置Cron表达式外,还可以通过fixedRate和fixedDelay两种方式设置定时任务,这两种方式可以自行了解。

执行结果

按照上面代码中给定的cron表达式@Scheduled(cron = "0/10 * * * * ? ")每十秒执行一次,那么最近几次的执行结果应当为:

5. 问题:执行时间延迟和单线程执行

 如果定时任务中是执行非常快的任务的,时间非常非常短,按照上述方法实现定时任务,确实不会有什么的延迟性,但真实的业务场景中,业务的执行时间可能远比这里时间长。

例如:主动让线程睡上20秒,让我们再来看看输出结果是如何的吧。

@Slf4j
@Component
@EnableScheduling
public class DemoTask {// 每10秒执行一次,cron的表达式暂时不多说明了,可以自行百度学习@Scheduled(cron = "0/10 * * * * ? ")public void testSchedule() {try {Thread.sleep(20000); // 休眠20秒,模拟业务场景执行时间log.info("当前执行任务的线程号ID===>{}", Thread.currentThread().getId()); // 日志输出} catch (Exception e) {e.printStackTrace();}}
}

执行结果

  • 执行时间延迟:从时间上可以明显看出,不再是每10秒执行一次,执行时间延迟很多,造成任务的。
  • 单线程执行:从始至终都只有一个线程在执行任务,造成任务的堵塞。

5.1 问题原因 

  • 任务阻塞:定时任务设置了每10秒执行一次,但任务实际执行了20秒,那么下一个任务的执行就会因为前一个任务尚未完成而被阻塞。
  • 单线程调度器:当使用@EnableScheduling默认配置创建定时任务时,通常Spring会使用一个单线程的TaskScheduler来执行这些定时任务。在默认配置下,这个单线程的调度器会顺序地执行每一个任务,而不会并行处理。

归根到底,线程阻塞式执行,执行任务线程数量过少 ~

5.2 解决方式

方式一:执行逻辑改为异步

首先我们先配置一个线程池,参数自己设置即可,我这里比较随意。

@Configuration
public class DemoTheadPoolConfig {@Bean(name = "TaskExecutor")public TaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//设置核心线程数executor.setCorePoolSize(10);//设置最大线程数executor.setMaxPoolSize(20);//缓冲队列200:用来缓冲执行任务的队列executor.setQueueCapacity(200);//线程活路时间 60 秒executor.setKeepAliveSeconds(60);//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池executor.setThreadNamePrefix("demo-thread-");//设置拒绝策略executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.setWaitForTasksToCompleteOnShutdown(true);return executor;}
}

然后在定时任务中的将模拟业务的休眠20秒,改造成多线程并发的方式执行。

    @Scheduled(cron = "0/10 * * * * ? ")public void testSchedule() {CompletableFuture.runAsync(() -> {try {Thread.sleep(20000); // 休眠20秒,模拟业务场景执行时间log.info("当前执行任务的线程号ID===>{}", Thread.currentThread().getId()); // 日志输出} catch (Exception e) {e.printStackTrace();}}, taskExecutor);}

执行结果

 可以看到虽然业务执行时间仍然是20秒,但是10秒的定时任务没有再出现延迟执行的情况。

方式二:异步定时任务

异步定时任务其实和上面的方式原理是一样的,不过实现稍稍不同罢了,在定时任务的类上再加一个@EnableAsync注解,给方法添加一个@Async即可。

注意:

  • @EnableAsync:开启异步任务
  • @Async:给希望异步执行的方法标注
  • 一般使用@Async都会指定线程池,比如写成这样@Async(value = "TaskExecutor")

@Slf4j
@Component
@EnableAsync
@EnableScheduling
public class DemoTask {// 每10秒执行一次,cron的表达式暂时不多说明了,可以自行百度学习@Async("TaskExecutor")@Scheduled(cron = "0/10 * * * * ? ")public void testSchedule() {try {Thread.sleep(20000); // 休眠20秒,模拟业务场景执行时间log.info("当前执行任务的线程号ID===>{}", Thread.currentThread().getId()); // 日志输出} catch (Exception e) {e.printStackTrace();}}
}

执行结果

结果显而易见也是和第一种方式一样的。


至此,我们的SpringBoot实现定时任务项目完美竣工!!!

ps:本教程我所阐述的这种方式,只能说适用于简单的单体项目,实际业务比这要复杂的多,如分布式场景还需考虑定时任务在多个机器下运行的问题,后续作者也会针对该问题出一篇分布式锁的教程,如感兴趣关注点一下吧!!!

有什么问题都可以评论区留言,看见都会回复的!!!

如果你觉得本篇文章对你有所帮助的,多多支持!!!

点赞收藏评论,抱拳了!!!

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 07:基础IO

stdin & stdout & stderr C默认会打开三个输入输出流&#xff0c;分别是stdin, stdout, stderr。仔细观察发现&#xff0c;这三个流的类型都是FILE*, fopen返回值类型&#xff0c;文件指针。 文件读取函数&#xff08;库函数&#xff09;&#xff1a; fopen、fread、…

部分功能的实现和算法

目录 1.雪花算法 2.MD5加密 3.小眼睛显示密码 4.发送验证码 5.倒计时 1.雪花算法 SnowFlake 中文意思为雪花&#xff0c;故称为雪花算法。最早是 Twitter 公司在其内部用于分布式环境下生成唯一 ID。在2014年开源 scala 语言版本 雪花算法的原理就是生成一个的 64 位比特…

电力需求预测挑战赛笔记 Task2 Datawhale AI 夏令营

#AI夏令营 #Datawhale #夏令营 Task1文章链接&#xff1a; 电力需求预测挑战赛笔记 Taks1 跑通baseline-CSDN博客文章浏览阅读577次&#xff0c;点赞5次&#xff0c;收藏9次。电力需求预测挑战赛;【训练时序预测模型助力电力需求预测】https://blog.csdn.net/qq_23311271/art…

【数据结构】二叉树———Lesson2

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

如何走出低能量状态?

晚上好。 每个人都难免会有状态不佳的时候。可能是遭受压力&#xff0c;可能是事情不顺&#xff0c;也可能无缘无故、突然就陷入情绪的低谷之中。 这时&#xff0c;我们很容易感到精力不济&#xff0c;无精打采&#xff0c;明明有许多事情要做和想做&#xff0c;但总是提不起精…

JavaWeb入门程序解析(Spring官方骨架、配置起步依赖、SpringBoot父工程、内嵌Tomcat)

3.3 入门程序解析 关于web开发的基础知识&#xff0c;我们可以告一段落了。下面呢&#xff0c;我们在基于今天的核心技术点SpringBoot快速入门案例进行分析。 3.3.1 Spring官方骨架 之前我们创建的SpringBoot入门案例&#xff0c;是基于Spring官方提供的骨架实现的。 Sprin…

DevExpress WPF中文教程 - 为项目添加GridControl并将其绑定到数据

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

springboot+vue+mybatis销售评价系统+PPT+论文+讲解+售后

随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;销售评价系统当然也不能排除在外。销售评价系统是以实际运用为开发背景&#xff0c;运用软件工程开发方法&#xff0c;采用Java…

Three.js 实战【2】—— 船模型海上场景渲染

停止了好久没有更新three这方面的文章了&#xff0c;从上两年还是vue2&#xff0c;一下子都换到vue3了&#xff0c;下面这些three都是基于vue3来进行开发的哈&#xff0c;先看一下这篇文章实现的效果哈。其中关于模型什么的资源都放在Git上了 初始化场景 安装three就直接通过n…

GuLi商城-商品服务-API-品牌管理-品牌分类关联与级联更新

先配置mybatis分页&#xff1a; 品牌管理增加模糊查询&#xff1a; 品牌管理关联分类&#xff1a; 一个品牌可以有多个分类 一个分类也可以有多个品牌 多对多的关系&#xff0c;用中间表 涉及的类&#xff1a; 方法都比较简单&#xff0c;就不贴代码了

000007 - HDFS DataNode

HDFS DataNode 1. DataNode工作机制2. DataNode的数据完整性3. 掉线时限参数设置 1. DataNode工作机制 &#xff08;1&#xff09;一个数据块在 DataNode 上以文件形式存储在磁盘上&#xff0c;包括两个文件&#xff0c;一个是数据本身&#xff0c;一个是元数据包括数据块的长度…

【C++】类与对象的学习(中)

目录 一、默认成员函数&#xff1a; 二、构造函数&#xff1a; 1、定义&#xff1a; 2、理解&#xff1a; 三、析构函数&#xff1a; 1、定义&#xff1a; 2、理解&#xff1a; 四、拷贝构造&#xff1a; 1、定义&#xff1a; 2、理解&#xff1a; 五、运算符的重载&…

夏令营入门组day5

目录 一. 城市距离 二. 史莱姆 一. 城市距离 &#xff08;1&#xff09;思路 每次询问&#xff0c;对于每一个点都判断与下一个点是否为临近点会超时&#xff0c;因此预处理&#xff0c;预先判断每一个点的临近点&#xff0c;然后将花费存入前缀和数组&#xff0c;这样在每次询…

对redis进行深入学习

目录 1. 什么是redis&#xff1f;1.1 为什么使用redis作为缓存&#xff1f;1.1.0 数据库&#xff08;MySQL&#xff09;与 redis1. 存储介质不同&#xff08;408选手应该都懂hh&#xff09;2. 数据结构优化3. I/O模型差异4. CPU缓存友好性5. 单线程与多线程差异6. 持久化与缓存…

哈尔滨网站建设注意哪些问题

在进行哈尔滨网站建设时&#xff0c;需要注意以下几个问题&#xff1a; 首先&#xff0c;要明确网站的定位和目标。网站建设的首要任务是明确网站的定位和目标&#xff0c;确定网站所要传达的信息和服务内容&#xff0c;以及面向的目标用户群体。哈尔滨作为一个具有浓厚地域特色…

Linux脚本:如何编写bash脚本统计多个相关进程的CPU占用率,以此统计系统中指定多进程的总的CPU使用率

目录 一、需求 二、分析 三、脚本示例 1、创建脚本 2、编写脚本 3、脚本编写注意事项 &#xff08;1&#xff09;CPU占用率列 &#xff08;2&#xff09;多进程实例 &#xff08;3&#xff09;权限 四、运行脚本 1、给予脚本可执行权限 2、运行脚本 五、优化脚本 …

linux live555编译以及rtsp服务器搭建

一、live555源码 下载&#xff1a;点击跳转 二、编译 1、往文件 config.linux里的 COMPILE_OPTS 添加以下两个参数 -DNO_STD_LIB 和 -DNO_OPENSSL1 &#xff0c;修改后如下&#xff1a; COMPILE_OPTS $(INCLUDES) -I/usr/local/include -I. -O2 -DNO_STD_LIB -DNO_OPENSS…

大数减法c++

这里写目录标题 key key 检查减数和被减数的大小&#xff0c;大的放前&#xff0c;小的放后确定结果是正数&#xff0c;还是负数&#xff0c;即符号位从低位开始减如果a[i]<b[i]&#xff0c;则向高位借1当10&#xff0c;a[i1]–;a[i]10 #include <iostream> #include…

【python】OpenCV—Coordinates Sorted Clockwise

文章目录 1、需求介绍2、算法实现3、完整代码 1、需求介绍 调用 opencv 库&#xff0c;绘制轮廓的矩形边框&#xff0c;坐标顺序为右下→左下→左上→右上&#xff0c;我们实现一下转化为熟悉的 左上→右上→右下→左下 形式 按照这样的顺序组织边界框坐标是执行透视转换或匹…

采用反相正基准电压电路的反相运算放大器(运放)

采用反相正基准电压电路的反相运算放大器(运放) 采用反相正基准电压电路的同相运算放大器&#xff08;运放&#xff09; 设计目标 输入ViMin输入ViMax输出VoMin输出VoMax电源电压Vcc电源电压Vee电源电压Vref-5V-1V0.05V3.3V5V0V5V 设计说明1 此设计使用具有反相正基准的反…