Spring Boot 2.x基础教程之使用@Scheduled实现定时任务的方法

 更新时间:2021年07月15日 10:42:57   作者:程序猿DD  
在Spring Boot中编写定时任务是非常简单的事,下面通过实例介绍如何在Spring Boot中创建定时任务,实现每过5秒输出一个当前时间,感兴趣的朋友跟随小编一起看看吧

我们在编写Spring Boot应用中经常会遇到这样的场景,比如:我需要定时地发送一些短信、邮件之类的操作,也可能会定时地检查和监控一些标志、参数等。

创建定时任务

在Spring Boot中编写定时任务是非常简单的事,下面通过实例介绍如何在Spring Boot中创建定时任务,实现每过5秒输出一下当前时间。

在Spring Boot的主类中加入@EnableScheduling注解,启用定时任务的配置

@SpringBootApplication
@EnableScheduling
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}

创建定时任务实现类

@Component
public class ScheduledTasks {

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    @Scheduled(fixedRate = 5000)
    public void reportCurrentTime() {
        log.info("现在时间:" + dateFormat.format(new Date()));
    }

}

运行程序,控制台中可以看到类似如下输出,定时任务开始正常运作了。

2021-07-13 14:56:56.413  INFO 34836 --- [           main] c.d.chapter71.Chapter71Application       : Started Chapter71Application in 1.457 seconds (JVM running for 1.835)
2021-07-13 14:57:01.411  INFO 34836 --- [   scheduling-1] com.didispace.chapter71.ScheduledTasks   : 现在时间:14:57:01
2021-07-13 14:57:06.412  INFO 34836 --- [   scheduling-1] com.didispace.chapter71.ScheduledTasks   : 现在时间:14:57:06
2021-07-13 14:57:11.413  INFO 34836 --- [   scheduling-1] com.didispace.chapter71.ScheduledTasks   : 现在时间:14:57:11
2021-07-13 14:57:16.413  INFO 34836 --- [   scheduling-1] com.didispace.chapter71.ScheduledTasks   : 现在时间:14:57:16

@Scheduled详解

在上面的入门例子中,使用了@Scheduled(fixedRate = 5000) 注解来定义每过5秒执行的任务。对于@Scheduled的使用,我们从源码里看看有哪些配置:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {

	String CRON_DISABLED = ScheduledTaskRegistrar.CRON_DISABLED;

	String cron() default "";

	String zone() default "";

	long fixedDelay() default -1;

	String fixedDelayString() default "";

	long fixedRate() default -1;

	String fixedRateString() default "";

	long initialDelay() default -1;

	String initialDelayString() default "";

}

这些具体配置信息的含义如下:

  • cron:通过cron表达式来配置执行规则
  • zone:cron表达式解析时使用的时区
  • fixedDelay:上一次执行结束到下一次执行开始的间隔时间(单位:ms)
  • fixedDelayString:上一次任务执行结束到下一次执行开始的间隔时间,使用java.time.Duration#parse解析
  • fixedRate:以固定间隔执行任务,即上一次任务执行开始到下一次执行开始的间隔时间(单位:ms),若在调度任务执行时,上一次任务还未执行完毕,会加入worker队列,等待上一次执行完成后立即执行下一次任务
  • fixedRateString:与fixedRate逻辑一致,只是使用java.time.Duration#parse解析
  • initialDelay:首次任务执行的延迟时间
  • initialDelayString:首次任务执行的延迟时间,使用java.time.Duration#parse解析

思考与进阶

是不是这样实现定时任务很简单呢?那么继续思考一下这种实现方式是否存在什么弊端呢?

可能初学者不太容易发现问题,但如果你已经有一定的线上项目经验的话,问题也是显而易见的:这种模式实现的定时任务缺少在集群环境下的协调机制。

什么意思呢?假设,我们要实现一个定时任务,用来每天网上统计某个数据然后累加到原始数据上。我们开发测试的时候不会有问题,因为都是单进程在运行的。但是,当我们把这样的定时任务部署到生产环境时,为了更高的可用性,启动多个实例是必须的。此时,时间一到,所有启动的实例就会同时开始执行这个任务。那么问题也就出现了,因为有累加操作,最终我们的结果就会出现问题。

解决这样问题的方式很多种,比较通用的就是采用分布式锁的方式,让同类任务之前的时候以分布式锁的方式来控制执行顺序,比如:使用Redis、Zookeeper等具备分布式锁功能的中间件配合就能很好的帮助我们来协调这类任务在集群模式下的执行规则。

代码示例

本文的完整工程可以查看下面仓库中的chapter7-1目录:

Github:https://github.com/dyc87112/SpringBoot-Learning/

Gitee:https://gitee.com/didispace/SpringBoot-Learning/

到此这篇关于Spring Boot 2.x基础教程之使用@Scheduled实现定时任务的方法的文章就介绍到这了,更多相关Spring Boot 2.x定时任务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • RocketMQ消息积压原因及处理方法

    RocketMQ消息积压原因及处理方法

    RocketMQ是一种可靠的、可扩展的消息中间件,广泛应用于分布式系统中的消息通信,然而,在高并发的场景下,由于消息产生速度超过消费速度,可能会导致消息积压的问题,本文将介绍RocketMQ消息积压的原因和如何处理积压问题
    2023-06-06
  • Java动态编译执行代码示例

    Java动态编译执行代码示例

    这篇文章主要介绍了Java动态编译执行代码示例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • javaweb实现app扫码登录功能

    javaweb实现app扫码登录功能

    这篇文章主要为大家详细介绍了javaweb实现app扫码登录功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • SpringMVC中@ModelAttribute与@RequestBody的区别及说明

    SpringMVC中@ModelAttribute与@RequestBody的区别及说明

    这篇文章主要介绍了SpringMVC中@ModelAttribute与@RequestBody的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • java定时调度器(Quartz)使用实例

    java定时调度器(Quartz)使用实例

    这篇文章主要介绍了java开源定时调度器使用方法
    2013-12-12
  • 关于在Java中使用预定义类

    关于在Java中使用预定义类

    这篇文章主要介绍了关于在Java中使用预定义类,预定义类就是Java类库(或第三方库)中已经定义好的类,例如,Math 类和 Date 类,需要的朋友可以参考下
    2023-05-05
  • 详解Java中如何正确书写单例模式

    详解Java中如何正确书写单例模式

    一般单例都是五种写法:懒汉,饿汉,双重校验锁,静态内部类和枚举。本文整理了几种常见的单例写法,下面跟着小编一起来看下吧
    2017-01-01
  • Java拷贝文件夹和删除文件夹代码实例

    Java拷贝文件夹和删除文件夹代码实例

    这篇文章主要介绍了Java拷贝文件夹和删除文件夹代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • java 集合----Map、Collection

    java 集合----Map、Collection

    HashSet 的 add() 方法添加集合元素时实际上转变为调用 HashMap 的 put()方法来添加 key-value 对。HashMap 的 put() 方法.hashCode() 判断返回值相等,如果返回值相等则再通过 equals 比较也返回 true,最终认为key对象是相等的已经在HashMap中存在。
    2016-04-04
  • Java获取接口的所有实现类方法总结示例

    Java获取接口的所有实现类方法总结示例

    这篇文章主要给大家介绍了关于Java获取接口的所有实现类方法的相关资料,文中通过代码介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-06-06

最新评论