SpringBoot – 定时任务入门(@Scheduled )详解

SpringBoot – 定时任务入门(@Scheduled )详解项目开发中经常需要执行一些定时任务 比如需要在每天凌晨时候 分析一次前一天的日志信息 Spring 为我们提供了异步执行任务调度的方式 提供 TaskExecutor TaskSchedule 接口 SpringBoot 中使用两个注解 EnableSchedu Scheduled 来简单实现定时任务 1 Scheduled 注解按照惯例 先看源码

项目开发中经常需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息。Spring为我们提供了异步执行任务调度的方式,提供TaskExecutor 、TaskScheduler 接口。

SpringBoot中使用两个注解:@EnableScheduling、@Scheduled来简单实现定时任务。

【1】@Scheduled注解

按照惯例,先看javadoc源码:

  • 使一个方法定时被执行的注解。其属性cron/fixedDelay/fixedRate必须有一个被指定
  • 该注解标记的方法没有参数,也没有返回值。即使写了返回值,也会被忽略。
  • 该注解被ScheduledAnnotationBeanPostProcessor处理器解析。
  • 可以手动注册该bean,当然更方便的是使用
    配置或者@EnableScheduling注解。

这个注解可以用来作为一个meta-annotation通过属性覆盖去创建自定义的组合注解。

@Target({ 
   ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(Schedules.class) public @interface Scheduled { 
    // cron表达式 String cron() default ""; //corn表达式的时区,默认为空,使用服务器的local time zone。 String zone() default ""; // 周期为在最后一次调用结束和下一次调用开始,以毫秒为单位,固定周期地执行注释的方法。 long fixedDelay() default -1; //周期间隔为在最后一次调用结束和下一次调用开始,以毫秒为单位,固定周期地执行注释的方法。 String fixedDelayString() default ""; //固定周期地执行注解方法,周期为调用间隔,单位为毫秒 long fixedRate() default -1; String fixedRateString() default ""; // fixedRate() 或fixedDelay()第一次执行前延迟的毫秒数 long initialDelay() default -1; // fixedRate() 或fixedDelay()第一次执行前延迟的毫秒数 String initialDelayString() default ""; } 

【2】@EnableScheduling 注解

启动Spring的定时任务执行能力,通常用在配置类上面,类似于xml片段

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(SchedulingConfiguration.class) @Documented public @interface EnableScheduling { 
    } 

该注解会使Spring 容器中所有bean中的@Scheduled注解起作用。如下所示,给定一个类MyTask :

package com.myco.tasks; public class MyTask { 
    // 每1000ms 执行一次该方法 @Scheduled(fixedRate=1000) public void work() { 
    // task execution logic } } 

如下配置确保MyTask.work()每1000ms被调用一次。

@Configuration @EnableScheduling public class AppConfig { 
    @Bean public MyTask task() { 
    return new MyTask(); } } 

如果MyTask使用了注解@Component,下面的配置将会确保其@Scheduled标注的方法会被以期望的间隔进行调用。

 @Configuration @EnableScheduling @ComponentScan(basePackages="com.myco.tasks") public class AppConfig { 
    } 

甚至可以直接在配置类中写@Scheduled注解标注的方法。

@Configuration @EnableScheduling public class AppConfig { 
    * @Scheduled(fixedRate=1000) public void work() { 
    // task execution logic } } 

默认,将会寻找一个相关联的scheduler ,可能是上下文中一个唯一的TaskScheduler或者一个bean id为taskSchedulerScheduledExecutorService也将执行同样的查找。如果上面两个定时任务处理器都没有被找到,一个本地单线程默认scheduler 将会被创建并被注册器使用。

如果想获得更多的控制,配置类应该实现SchedulingConfigurer接口。这将可以获取底层的ScheduledTaskRegistrar实例。

下面的例子演示了如何自定义Executor去执行定时任务。

@Configuration @EnableScheduling public class AppConfig implements SchedulingConfigurer { 
    @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { 
    taskRegistrar.setScheduler(taskExecutor()); } @Bean(destroyMethod="shutdown") public Executor taskExecutor() { 
    return Executors.newScheduledThreadPool(100); } } 

注意上面例子中@Bean(destroyMethod="shutdown")的使用。这将确保线程任务执行器在Spring容器被销毁时正确的关闭。实现SchedulingConfigurer还可以通过ScheduledTaskRegistrar对任务注册实细粒度的控制。 例如,以下为每个自定义Trigger实现配置特定bean方法的执行

 @Configuration @EnableScheduling public class AppConfig implements SchedulingConfigurer { 
    @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { 
    taskRegistrar.setScheduler(taskScheduler()); taskRegistrar.addTriggerTask( new Runnable() { 
    public void run() { 
    myTask().work(); } }, new CustomTrigger() ); } @Bean(destroyMethod="shutdown") public Executor taskScheduler() { 
    return Executors.newScheduledThreadPool(42); } @Bean public MyTask myTask() { 
    return new MyTask(); } } 

作为参考,可以将上面的示例与下面的Spring XML配置进行比较

<beans> <task:annotation-driven scheduler="taskScheduler"/> <task:scheduler id="taskScheduler" pool-size="42"/> <task:scheduled-tasks scheduler="taskScheduler"> <task:scheduled ref="myTask" method="work" fixed-rate="1000"/>  
     task:scheduled-tasks> <bean id="myTask" class="com.foo.MyTask"/>  
      beans> 

更多参考Scheduled、SchedulingConfiguration、SchedulingConfigurer、ScheduledTaskRegistrar、Trigger以及ScheduledAnnotationBeanPostProcessor。

【3】代码实例

Service如下(这里使用cron表达式):

@Service public class ScheduledService { 
    // 每天的整分调用一次该方法 @Scheduled(cron = "0 * * * * 0-7") public void hello(){ 
    System.out.println("hello..."); } } 

在主程序上添加@EnableScheduling注解如下:

@SpringBootApplication @EnableScheduling public class SpringBoot01CacheApplication { public static void main(String[] args) { SpringApplication.run(SpringBoot01CacheApplication.class, args); } } 

这里写图片描述


fixedRate ,fixedDelay 和initialDelay

代码示例如下:

 //上一次 项目启动时间点之后 5 秒执行一次 @Scheduled(fixedRate = 5000) public void fixedRate(){ System.out.println("fixedRate: " + new SimpleDateFormat("HH:mm:ss").format(new Date())); } //上一次 结束时间点之后 每50秒执行一次 @Scheduled(fixedDelay = 50000) public void fixedDelay(){ for (int i = 0; i < 10; i++){ System.out.println("fixedDelay" + i + new SimpleDateFormat("HH:mm:ss").format(new Date())); } } // initialDelay :fixedRate() 或fixedDelay()第一次执行前延迟的毫秒数 //第一次延迟50秒执行,之后按照fixedRate的规则每6秒执行一次 @Scheduled(initialDelay = 50000,fixedRate = 6000) public void initialDelayFixedRate (){ for (int i = 0; i < 10; i++){ System.out.println("initialDelayFixedRate :" + i + new SimpleDateFormat("HH:mm:ss").format(new Date()) ); } } 

【4】cron表达式

cron表达式属性如下:

second(秒), minute(分), hour(时),day of month(日),month(月),day of week(周几) 

字段与值表格如下:

字段 允许值 允许的特殊符号
0-59 ,-*/
0-59 ,-*/
小时 0-23 ,-*/
日期 1-31 ,-*?/LWC
月份 1-12 ,-*/
星期 0-7或SUN-SAT 0 7是SUN ,-*?/LC#

特殊符号释义如下:

特殊符号 代表含义
, 枚举
- 区间
* 任意
/ 步长
? 日/星期冲突匹配
L 最后
W 工作日
C 和Calendar联系后计算过的值
# 星期 4#2 第2个星期四

示例如下:

0 0 0 * * * -- 每天零时执行一次 0 0/15 14,18 * * ? -- 每天14点整和18点整,每隔15分钟执行一次 0 15 10 ? * 1-6 -- 每个月的周一到周六 10:15分执行一次 0 0 2 ? * 6L -- 每个月的最后一个周六凌晨2点执行一次 0 0 2 LW * ? -- 每个月的最后一个工作日凌晨2点执行一次 0 0 2-4 ? * 1#1 -- 每个月的第一个周一凌晨2点到4点期间,每个整点都执行一次 

实现定时任务的方式很多,其他的有JDK 自带的 TimerTask or Timer、使用开源作业调度框架 Quartz、线程池 ScheduleExecutorService 和其实现类ScheduledThreadPoolExecutor

参考博文:多线程并发之Executor。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/225131.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 上午10:02
下一篇 2026年3月17日 上午10:03


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号