SpringBoot中的定时任务@Scheduled的使用

这篇具有很好参考价值的文章主要介绍了SpringBoot中的定时任务@Scheduled的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.@Scheduled注解介绍

在spring boot的项目中需要使用到定时任务的时候,可以使用@Scheduled注解,这只是在一个JVM进程中很适用,如果涉及到服务器是集群的情况下,建议使用任务调度平台。这样任务调度平台会在多台服务器中选择一台进行定时任务的执行。该注解位于spring-context.jar包中

springboot 使用scheduled,spring boot,spring,java

 2.@Scheduled相关属性说明

属性 说明
cron():String 使用Cron表达式创建定时任务,值可以是字符串也“0 * * * * MON-FRI”可以是${...}获取配置文件中定义的表达式
zone():String 指定cron的时区,默认是空字符串,表示本地时区
fixedDelay():long 任务执行的时间间隔,表示第一次任务执行完毕和第二次任务开始之间的时间,单位:毫秒
fixedRate():long 每隔多久执行一次任务,第一次任务开始和第二次任务开始之间的时间,单位:毫秒
initialDelay():long 表示第一次执行fixedDelayfixedRate要等待的时间,单位:毫秒

3.@Scheduled简单使用

(1)首先要知道@Scheduled注解要生效需要在系统启动类或配置类上添加@EnableScheduling注解,这里在系统的启动类上加@EnableScheduling注解。如下所示:

springboot 使用scheduled,spring boot,spring,java

(2)创建一个定时任务类TestSchedule,使用@Component注解标注,交给容器管理。定义一个方法taskScheduledOne,并在方法上加上注解@Scheduled以及cron表达式,如下图所示@Scheduled(cron = "0/10 * * * * ?")表示该定时任务每10秒钟执行一次。

springboot 使用scheduled,spring boot,spring,java

 (3)执行效果如下:

springboot 使用scheduled,spring boot,spring,java

如上图的打印效果所示, 到这里,一个简单的定时任务就已经完成了

4.可能出现的问题一:两个定时任务执行时间间隔问题

测试代码如下所示:

@Component
public class TestSchedule {

    /**
     * 每十秒钟执行一次
     */
    @Scheduled(cron = "0/10 * * * * ?")
    public void taskScheduledOne() throws InterruptedException {
        Thread t = Thread.currentThread();
        System.out.println("taskScheduledOne "+ DateTimeUtils.dateToString(new Date()) +" ThreadID:"+ t.getId() +" "+t.getName());
        Thread.sleep(5000);
        System.out.println("taskScheduledOne End " + DateTimeUtils.dateToString(new Date()) + " ThreadID:" + t.getId() + " " + t.getName());
    }

    /**
     * 每三秒钟执行一次
     */
    @Scheduled(cron = "0/3 * * * * ?")
    public void taskScheduledTwo() {
        Thread t = Thread.currentThread();
        System.out.println("taskScheduledTwo " + DateTimeUtils.dateToString(new Date()) + " ThreadID:" + t.getId() + " " + t.getName());
    }

}

运行代码,最初的部分结果打印如图所示:我们发现定时任务2和定时任务1都是一个线程(线程id为48)执行的,定时任务2是每3秒钟执行一次,但这里出现了问题,如下图中的箭头所示,定时任务2在“ 2023/06/08 20:24:39 ”执行完,下一次的执行完的时间按理说应该是“ 2023/06/08 20:24:42 ”,但结果显示时间是2023/06/08 20:24:45,说明这里出现了问题。

问题解释:因为Spring中@EnableScheduling和@Scheduled标注的定时任务默认是单线程执行的,所以定时任务2 在箭头A 执行完,定时任务1开始执行,定时任务1 和 定时任务2 都是同一个线程执行的,这里的定时任务1执行花费5s左右的时间,已经超过了定时任务2的3s执行周期,导致定时任务2被阻塞了。所以定时任务2再执行打印时,就出现在箭头B这个地方了,时间差已经超过了3s。

springboot 使用scheduled,spring boot,spring,java

 5.可能出现的问题二:使用@Async和@EnableAsync异步执行任务

 Spring的定时任务包中提供了@EnableAsync和@Async注解用于多线程异步执行任务。

在启动类上添加@EnableAsync注解,并在TestSchedule类上标注@Async注解,表示该类中所有标注了@Scheduled的方法都使用异步处理方式。

springboot 使用scheduled,spring boot,spring,java

 springboot 使用scheduled,spring boot,spring,java

 再次执行之前的代码看一下效果:

定时任务2时间间隔均是3s,定时任务1时间间隔也是10s,且非单线程操作了。

springboot 使用scheduled,spring boot,spring,java

 这里看似解决了上述问题一,但其实可能会引入第二个问题,就是定时任务的执行时间过长,超过定时任务执行的周期。修改一下上述的代码,将定时任务1线程沉睡的时间由5s改为11s。再次执行代码:

Thread.sleep(5000);
// 改为
Thread.sleep(11000);

执行效果如下:定时任务2正常执行。但定时任务1执行出现了线程交叉执行。

原因解释:定时任务1的执行时间超过了定时任务的执行周期,在某个线程执行定时任务1时,还没结束,下一个线程又开始执行定时任务1了,这就是使用@EnableAsync和@Async异步执行定时任务可能会出现的问题。

springboot 使用scheduled,spring boot,spring,java

 springboot 使用scheduled,spring boot,spring,java

 6.问题一和问题二的解决方案

(1)去掉如下注释的注解

springboot 使用scheduled,spring boot,spring,java

 

springboot 使用scheduled,spring boot,spring,java

 (2)创建一个任务配置类ScheduleConfig 实现SchedulingConfigurer接口的configureTasks方法,使用参数taskRegistrar为任务调度创建线程池;

@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean(destroyMethod = "shutdown")
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(10);
    }
    
}

运行结果如下图所示:定时任务2执行正常,定时任务1执行也正常,不会出现交叉现象,定时任务1第二次执行的时间会等第一次执行完毕之后下一个任务任务调度时间点开始才会执行。

springboot 使用scheduled,spring boot,spring,java

 springboot 使用scheduled,spring boot,spring,java

 7.总结

SpringBoot中可以使用@EnableScheduling和@Scheduled注解实现定时任务调度,但是注意默认所有任务都被单个线程调度的,有可能任务之间发生阻塞现象,可以使用@EnableAsync和@Async注解实现异步多线程任务调度,但需要注意任务执行时间如果大于任务调度周期时间,可能出现同一个任务交叉执行的情况。上述6可以解决相关问题。文章来源地址https://www.toymoban.com/news/detail-706811.html

到了这里,关于SpringBoot中的定时任务@Scheduled的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java Scheduled定时任务

    开启定时任务步骤流程: 1、在启动类添加注解;(注意:千万不要忘记!) @EnableScheduling 2、在具体的方法上添加定时任务注解 @Scheduled(cron = “0 0 */3 * * ?”) // 每3个小时触发一次 3、定时任务开启时间: 常用的: @Scheduled(cron = “0 0/1 * * * ?” ) //每一分钟启动一次 @Scheduled

    2024年02月10日
    浏览(42)
  • @Scheduled 定时任务不执行

    启动类上加 @EnableScheduling 注解 定时任务类上加@Component 定时方法上加@Scheduled 解决:进行try…catch异常抛出 原因是: @Scheduled注解会在默认情况下以单线程的方式执行定时任务。 这个“单线程”指两个方面: 如果一个定时任务执行时间大于其任务间隔时间,那么下一次将会等

    2024年02月05日
    浏览(69)
  • @Scheduled定时器 定时任务调度:Unexpected error occurred in scheduled task错误

    目录 一、基本使用 二、参数详解 1. @Scheduled(fixedDelay = 5000) 2. @Scheduled(fixedRate = 5000) 3. @Scheduled(cron = “0 0 2 * * ?”) 4.cron表达式 案例 配置文件 写配置的时候,没有提示,解决方案 三、@Scheduled注意事项 四、 @Scheduled 的执行原理  1、加载使用 @Scheduled 注解的类及方法  2、解析

    2024年02月16日
    浏览(51)
  • JAVA 定时任务@Scheduled设置

    例1:每隔5秒执行一次:*/5 * * * * ? 例2:每隔5分执行一次:0 */5 * * * ? 在26分、29分、33分执行一次:0 26,29,33 * * * ? 例3:每天半夜12点30分执行一次:0 30 0 * * ? (注意日期域为0不是24) 每天凌晨1点执行一次:0 0 1 * * ? 每天上午10:15执行一次: 0 15 10 ? * * 或 0 15 10 * * ? 或 0 15

    2023年04月16日
    浏览(53)
  • @Scheduled Cron定时任务——表达式详解

    Cron表达式是一种用于定时任务调度的字符串表达式,它由6个或7个字段组成,分别表示秒、分、时、日、月、周和年。每个字段用空格分隔,字段之间用逗号分隔。 秒(0-59) 分(0-59) 时(0-23) 日(1-31) 月(1-12) 周(0-7,其中0和7都表示周日) 年(可选字段,1970-2099) Cron表达式的语法规则如

    2024年02月09日
    浏览(44)
  • 异常 :Unexpected error occurred in scheduled task 。 Spring Boot定时任务调度注解@scheduled

           前言: @Scheduled 注解是 Spring Boot 提供的用于定时任务控制的注解,主要用于控制任务在某个指定时间执行,或者每隔一段时间执行        异常: Unexpected error occurred in scheduled task :计划任务发生意外错误 这个bug是偶然一次遇见的,当时觉得这个描述很简单,肯定

    2024年02月12日
    浏览(48)
  • Spring中的任务调度:探索@Scheduled和@Schedules注解的威力

    在现代应用程序开发中,执行定时任务是一个常见的需求。无论是定期执行批处理作业、发送电子邮件通知,还是清理无用数据,定时任务在许多应用中都扮演着重要角色。Spring框架为处理这一需求提供了强大的工具,其中 @Scheduled 和 @Schedules 注解就像是这个领域的秘密武器

    2024年02月08日
    浏览(58)
  • 一张思维导图带你学会使用SpringBoot中的Schedule定时发送邮件

    🧑‍💻作者名称:DaenCode 🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。 😎人生感悟:尝尽人生百味,方知世间冷暖。 📖所属专栏:SpringBoot实战 标题 一文带你学会使用SpringBoot+Avue实现短信通知功能(含重要文件代码) 一张思维导图带你学会Springboot创

    2024年02月14日
    浏览(89)
  • Spring@Scheduled定时任务接入XXL-JOB的一种方案(基于SC Gateway)

    目前在职的公司,维护着Spring Cloud分布式微服务项目有25+个。其中有10个左右微服务都写有定时任务逻辑,采用Spring @Scheduled这种方式。 Spring @Scheduled定时任务的缺点: 不支持集群:为避免重复执行,需引入分布式锁 死板不灵活:不支持手动执行,单次执行,补偿执行,修改

    2024年02月11日
    浏览(48)
  • Java定时器 @Scheduled注解的使用

    @Scheduled注解可以用于做定时任务,再方法上加上@Scheduled注解,可以将这个方法定义为一个任务发放,可以搭配cron表达式进行任务的控制。 开启定时任务时在类上加注解 @EnableScheduling 1.按顺序依次为 秒 分 时 天 月 周 年 表达式长度为6个或者7个 cron表达式是一个字符串,分为

    2024年02月04日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包