# SpringBoot定时任务

# Spring Task

# 介绍

Spring Task 是Spring 框架内置的轻量化定时任务模块,不需要引物额外的配置。

支持通过注解和XML文件实现定时任务,本文主要介绍通过注解方式

# 准备工作

启动类添加@EnableScheduling注解

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

创建定时任务类,给方法添加@Scheduled注解

@Component
public class TaskJob {
    @Scheduled
    public void execute() {
        System.out.println("执行定时任务");
    }
}

# fixedDelay 固定延迟

fixedDelay可以确保上次任务结束和下次任务开始, 有n毫秒的延迟,适合对于上次运行结果存在依赖的任务

@Scheduled(fixedDelay = 1000L)
public void job2(){
    System.out.println("Fixed delay task - " + System.currentTimeMillis() / 1000);
}

运行结果:

Fixed delay task - 1734922190 Fixed delay task - 1734922191 Fixed delay task - 1734922192 Fixed delay task - 1734922193 Fixed delay task - 1734922194

每秒打印一次

如果任务用时较长

@Scheduled(fixedDelay = 1000L)
public void job2() throws InterruptedException {
    System.out.println("Fixed delay task - " + System.currentTimeMillis() / 1000);
    Thread.sleep(2000L);
}

运行结果:

Fixed delay task - 1734922277 Fixed delay task - 1734922280 Fixed delay task - 1734922283 Fixed delay task - 1734922286 Fixed delay task - 1734922289

每3秒执行一次:任务用时2秒、延迟1秒

# fixedRate 固定频率

fixedRate每 n 毫秒运行一次计划任务,不会检查任务之前的任何执行情况

@Scheduled(fixedRate = 1000L)
public void job3(){
    System.out.println("Fixed rate task - " + System.currentTimeMillis() / 1000);
}

运行结果:

Fixed rate task - 1734922424 Fixed rate task - 1734922425 Fixed rate task - 1734922426 Fixed rate task - 1734922427 Fixed rate task - 1734922428

和固定延迟类似

如果任务用时较长:

@Scheduled(fixedRate = 1000L)
public void job3() throws InterruptedException {
    System.out.println("Fixed rate task - " + System.currentTimeMillis() / 1000);
    Thread.sleep(2000L);
}

运行结果:

Fixed rate task - 1734922587 Fixed rate task - 1734922589 Fixed rate task - 1734922591 Fixed rate task - 1734922593 Fixed rate task - 1734922595

上一个任务结束,如果下一个任务的时间到了,会立刻执行

# initialDelay 初始延迟

和正常情况对比

@Scheduled(fixedRate = 1000L)
public void job3(){
    System.out.println("Fixed rate task - " + System.currentTimeMillis() / 1000);
}

@Scheduled(fixedDelay = 1000, initialDelay = 2000)
public void job4() {
    System.out.println("Fixed rate task with one second initial delay - " + System.currentTimeMillis() / 1000);
}

运行结果:

Fixed rate task - 1734922916 Fixed rate task - 1734922917 Fixed rate task - 1734922918 Fixed rate task with one second initial delay - 1734922918 Fixed rate task - 1734922919 Fixed rate task with one second initial delay - 1734922919 Fixed rate task - 1734922920 Fixed rate task with one second initial delay - 1734922920 Fixed rate task - 1734922921 Fixed rate task with one second initial delay - 1734922921 Fixed rate task - 1734922922 Fixed rate task with one second initial delay - 1734922922

会延迟设定的毫秒数,再执行任务

# 结合cron使用

@Scheduled(cron = "0/2 * * * * ?")
public void execute() {
    System.out.println("执行定时任务" + System.currentTimeMillis()/1000);
}

# Quartz(补充)

# Cron表达式详解

# 介绍

Cron 表达式是一种用于指定定时任务执行时间的字符串表达式。它由 6 个字段组成,分别表示秒、分钟、小时、天数、月份和星期几。每个字段都可以使用特定的符号来指定时间范围或间隔。

    ┌────────────── 秒 (Seconds) 0-59的整数
    | ┌──────────── 分钟 (Minutes) 0-59的整数
    | | ┌────────── 小时 (Hours) 0-23的整数
    | | | ┌──────── 天数 (DayofMonth) 1-31的整数,需要考虑具体月的天数
    | | | | ┌────── 月份 (Month) 1-12的整数,或者JAN-DEC
    | | | | | ┌──── 星期几 (DayofWeek) 1-7的整数或者 SUN-SAT (1=SUN)
    | | | | | | ┌── 年[可选] 1970~2099
    | | | | | | |
    * * * * * * * 命令

星期一 MON 星期二 TUE 星期三 WED 星期四 THU 星期五 FRI 星期六 SAT 星期天 SUN

1月 JAN 2月 FEB 3月 MAR 4月 APR 5月 MAY 6月 JUN 7月 JUL 8月 AUG 9月 SEP 10月 OCT 11月 NOV 12月 DEC

# 不同系统的差异

  • UNIX/Linux 的 cron 表达式是 5 位,不支持秒。
  • Quartz 的 cron 表达式是 6 位或 7 位(含年)
  • Spring Taskcron 表达式是 6 位 ,秒不可省略

# 特殊用法

除了基本的数字范围外,Cron 表达式还支持一些特殊符号和字符:

  • 星号*:表示匹配任意值。例如,* 在分钟字段中表示每分钟都执行。
  • 逗号,:用于分隔多个值。例如,1,3,5 在小时字段中表示 1 点、3 点和 5 点执行。
  • 斜线/:用于指定间隔值。例如,*/5 在分钟字段中表示每 5 分钟执行一次。
  • 连字符-:用于指定范围。例如,10-20 在日期字段中表示从 10 号到 20 号。
  • 问号?:仅用于DayofMonth和DayofWeek两个字段,表示不指定具体值。通常用于避免冲突。

扩展用法:(标准 UNIX cron 不支持,Quartz Scheduler 或 Spring Task支持)

  • L :表示最后,只能出现在DayofWeek和DayofMonth域,如果在DayofWeek域使用5L,意味着在最后的一个星期四触发
  • W:表示最近的工作日(周一到周五),只能出现在DayofMonth域,不能跨月
  • LW:表示在某个月最后一个工作日,即最后一个星期五

# 示例表达式

  • 0 0 12 * * ?:每天中午 12 点执行。
  • 0 0/5 * * * ?:每 5 分钟执行一次。
  • 0 0 8-18 ? * MON-FRI:周一至周五的 8 点到 18 点之间每小时执行一次
Last Updated: 12/23/2024, 4:18:13 AM