目录

Spring Boot - 定时任务

# 使用背景

定时任务在实际项目开发中很常见,并且定时任务可以在各种场景中应用,通过自动化操作和任务的规模化管理,提高效率、可靠性和工作质量。可以减少手动操作,避免疏忽和错误,并节省时间和人力资源的投入。

# 定时任务的优点

简单易用:使用注解驱动的方式,简化了定时任务的配置和管理。通过添加 @Scheduled 注解,可以将普通的方法标记为定时任务,而不需要手动编写定时任务调度的代码。

内置任务调度器:Spring Boot 内置了一个轻量级的任务调度器,可以方便地执行定时任务。它提供了线程池、任务管理和并发处理等功能,可以高效地管理和执行任务。

灵活的配置选项:@Scheduled 注解支持各种配置选项,例如 cron 表达式、fixedRate、fixedDelay 等,可以非常灵活地定义任务的触发时间和频率。这使得开发人员能够根据具体需求精确控制定时任务的执行方式。

总的来说,Spring Boot 定时任务提供了简单、灵活和可扩展的方式来进行任务调度。开发人员可以通过少量的配置和注解来创建定时任务,并利用 Spring 的特性和生态系统来增强定时任务的功能和性能。

# SpringBoot 实现定时任务

pom.xml

<!-- web -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok -->
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10

启动类使用 @EnableScheduling 来开启定时任务注解

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

// 开启定时任务注解
@EnableScheduling 
@SpringBootApplication
public class ScheduledApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScheduledApplication.class, args);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

测试类

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Component
@Slf4j
public class ScheduledTest {
    /* 每两秒执行一次 */
    @Scheduled(cron = "0/2 * * * * ?")
    public void scheduledTasks() {
        log.info("根据cron表达式的定时执行规则,执行任务~");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

@Scheduled 使用了 cron 表达式。

# Cron 表达式

Cron 表达式由空格分隔的 6 个或 7 个字段组成,每个字段代表一个时间单位。字段的取值范围如下:

参数 是否必须 范围 支持的特殊字符
秒(Seconds) 0 ~ 59 *,- /
分(Minutes) 0 ~ 59 *,- /
时(Hours) 0 ~ 23 *,- /
日(DayofMonth) 1 ~ 31 *,- /? L W
月(Month) 1 ~ 12 *,- /
星期(DayofWeek) 1 ~ 7 *,- /? L #
年(Year) 1970 ~ 2099 - * /

# 特殊字符

  • *(星号):通配符,表示每个时间单位。例如 * * * * ? 表示每一秒执行一次

  • ?(问号):该字符用于在日期和星期字段中指定「不指定值」。一般情况下,日期和星期两个字段只能指定一个值,另一个字段要使用问号进行占位。例如 0 0 12 ? *,表示在每个星期一至星期五的 12 点执行

  • -(连字符):范围符号,用于指定一个时间单位的取值范围。例如 10-30 * * * * ? 表示在每分钟的第 10 秒到第 30 秒之间执行

  • ,(逗号):枚举符号,用于指定多个时间单位取值的列表。例如 1,3,5 * * * * ? 表示在每小时的第 1 分、第 3 分和第 5 分执行

  • /(斜杠):间隔符号,用于指定时间单位的间隔。例如 0/5 * * * * ? 表示每 5 秒执行一次

  • L(最后的):特殊字符,用于指定某个时间单位的最后一个值。例如 0 0 12 L * ? 表示在每个月的最后一天的 12 点执行

  • W(工作日):特殊字符,用于指定距离给定日期最近的工作日(周一至周五)。例如 15W * * * ? 表示在每个月的第 15 个工作日当天执行

  • #(井号):特殊字符,用于指定某个月份的第几个星期几。例如 0 0 12 ? * 6#3 表示在每个月的第三个星期五的 12 点执行

如果不记得规则,可以直接去 cron 在线网站生成即可,如:Cron 在线表达式生成器 (opens new window)

# 其他方式

@Scheduled 注解除了使用 cron,还有其他属性。

@Component
@Slf4j
public class SchedulerTask {
  /**
   * @Scheduled(fixedRate = 6000) :上一次开始执行时间点之后 6 秒再执行
   * @Scheduled(fixedDelay = 6000) :上一次执行完毕时间点之后 6 秒再执行
   * @Scheduled(initialDelay=1000, fixedRate=6000) :第一次延迟 1 秒后执行,之后按 fixedRate 的规则每 6 秒执行一次
   * 默认是毫秒,可以通过 timeUnit 修改时间单位
   */
  
  @Scheduled(fixedRate = 5000, timeUnit = TimeUnit.MILLISECONDS)
  public void scheduled1() {
    log.info("使用 fixedRate 执行定时任务");
  }
  
  @Scheduled(fixedRate = 5000, timeUnit = TimeUnit.MILLISECONDS)
  public void scheduled2() {
    log.info("使用 fixedDelay 执行定时任务");
  }
  
  @Scheduled(cron = "*/6 * * * * ?")
  private void scheduled3(){
    log.info("使用 cron 执行定时任务");
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 使用定时任务注意点

避免耗时操作

定时任务的执行应尽量避免执行长时间运行的操作,或者涉及到大量数据处理的任务。因为定时任务是按照预定的时间间隔循环执行的,如果任务执行时间过长,可能会导致任务堆积和性能下降。

处理异常情况

在定时任务的执行过程中,难免会遇到一些异常情况。需要确保任务的健壮性,即使出现异常也能够妥善处理,而不会导致整个任务调度系统的崩溃。

定时任务的幂等性

在设计定时任务时,需要考虑任务的幂等性,即任务可以重复执行而不会影响最终结果。确保任务的执行逻辑和数据操作是幂等的,以避免数据错误和重复处理的问题。

注意这些要点可以帮助你使用定时任务更加稳定和可靠。根据实际情况,可能还需要考虑其他的因素,如分布式环境下的任务调度、任务依赖关系、任务优先级等。

更新时间: 2024/01/17, 05:48:13
最近更新
01
JVM调优
12-10
02
jenkins
12-10
03
Arthas
12-10
更多文章>