Spring Task 是 Spring 框架提供的任务调度工具,主要用于实现定时任务和多线程任务的管理。它是基于 @Scheduled
注解和 TaskScheduler
接口实现的,使用方便,并且集成到 Spring 框架中,允许我们使用声明式的方法来定义和管理任务。
1.Spring Task 的特点
- 简单集成:它是 Spring 框架的一部分,无需额外配置,使用方便。
- 强大的调度功能:支持多种方式的任务调度,例如固定频率、固定延迟以及 Cron 表达式。
- 支持并发执行:可以灵活配置任务执行的线程池,管理并发任务的执行。
2.使用步骤
2.1. 添加依赖
Spring Task 通常是包含在 Spring Boot 项目中的。如果使用 Spring Boot,只需要在 pom.xml
中添加 Spring Boot Starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
2.2. 启用定时任务
要在 Spring 项目中启用定时任务,需要在主类或配置类上添加 @EnableScheduling
注解。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class SpringTaskApplication {
public static void main(String[] args) {
SpringApplication.run(SpringTaskApplication.class, args);
}
}
2.3. 创建定时任务
使用 @Scheduled
注解来创建定时任务。@Scheduled
支持以下几种调度方式:
-
fixedRate
:固定频率执行,即任务开始执行后等待固定的时间间隔再执行。 -
fixedDelay
:固定延迟执行,即任务结束后等待固定的时间间隔再执行。 -
cron
:通过 Cron 表达式定义复杂的调度规则。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTasks {
// 每隔 5 秒执行一次
@Scheduled(fixedRate = 5000)
public void fixedRateTask() {
System.out.println("Fixed rate task - " + System.currentTimeMillis() / 1000);
}
// 每次执行完成后延迟 5 秒再执行
@Scheduled(fixedDelay = 5000)
public void fixedDelayTask() {
System.out.println("Fixed delay task - " + System.currentTimeMillis() / 1000);
}
// 使用 Cron 表达式:每分钟的第 0、15、30、45 秒执行
@Scheduled(cron = "0,15,30,45 * * * * ?")
public void cronTask() {
System.out.println("Cron task - " + System.currentTimeMillis() / 1000);
}
}
3.Cron 表达式简介
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class SchedulerConfig {
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5); // 设置线程池大小
scheduler.setThreadNamePrefix("spring-task-thread-");
return scheduler;
}
}
Cron 表达式的格式为:秒 分 时 日 月 周 [年]
,各字段取值说明如下:
- 秒(0-59)
- 分(0-59)
- 时(0-23)
- 日(1-31)
- 月(1-12)
- 周(0-7,其中0和7都表示周日)
例如,@Scheduled(cron = "0 0 12 * * ?")
表示每天中午 12 点执行。
4.配置线程池
默认情况下,Spring Task 使用单线程来执行任务。如果有多个任务并且希望它们并行执行,可以配置一个任务调度线程池。
首先,创建一个配置类,用于定义线程池:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class SchedulerConfig {
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5); // 设置线程池大小
scheduler.setThreadNamePrefix("spring-task-thread-");
return scheduler;
}
}
注意事项
-
任务阻塞:如果某个任务的执行时间超过了调度间隔,可能会导致任务阻塞。因此应尽量确保任务执行的时间不超过间隔。
-
幂等性:定时任务有时可能会重复执行,因此任务逻辑应保证幂等性,即相同任务重复执行不会产生不同的结果。
-
异常处理:任务中如果出现未捕获的异常,任务将会停止运行。因此应在任务代码中使用适当的异常处理机制。