一、引入依赖
定时任务是spring boot框架提供的基础能力之一,所以其依赖是在spring-boot-starter里面,但是一般开发的时候我们直接引入web依赖即可,web依赖中包含了spring-boot-starter。要注意的是Spring Boot 从版本1.3.0开始提供对定时任务的支持,本文用的依赖默认是支持定时任务的版本。
<dependencies>
<!-- Spring Boot Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
二、如何使用定时任务
2.1 开启定时任务注解
使用@EnableScheduling
注解开启定时任务,通常在启动类、配置类中使用该注解开启定时任务
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
2.2 使用@Scheduled
注解来创建定时任务,设置定时任务时间
创建一个类,该类要被SpringBoot管理起来,故通常添加@Component或@Configuration
注解,以将其标记为Spring组件。
然后创建需要定时执行的方法,在方法使用@Scheduled
注解来创建定时任务。使用fixedRate
属性可以指定任务的执行频率,单位默认是毫秒。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class YourScheduledTask {
@Scheduled(fixedRate = 5000) // 每隔5秒执行一次任务
public void yourTask() {
// 执行你的任务逻辑
}
}
这里设置为5000毫秒(5秒)
2.3 运行你的Spring Boot应用,定时任务将会自动执行
请注意,在以上的例子中,定时任务是基于单个线程池来执行的,默认是一个单线程的线程池。如果需要执行大量的定时任务,或者有一些耗时的任务,你可能需要配置一个线程池来提高性能。你可以在配置文件中添加以下属性来自定义线程池配置:
# application.properties
spring.task.scheduling.pool.size=10
上述配置将创建一个大小为10的线程池。
三、cron表达式
@Scheduled注解还可以使用cron表达式来定义定时任务的执行条件的。cron表达式由6个字段组成,分别表示秒、分、时、日、月、周几。每个字段都可以接受特定的取值范围或通配符来表示时间的匹配规则。
在线生成cron表达式的地址: 在线Cron表达式生成器
3.1 时间范围
Cron表达式由空格分隔的6个或7个字段组成,每个字段代表一个时间单位。字段的取值范围如下:
SpringBoot的cron表达式是不包含年(Year)的前六位
3.2 特殊字符
以下是一些示例cron表达式的用法:
0 0 0 * * *
:每天凌晨执行任务0 0/5 * * * *
:每隔5分钟执行任务0 0 9-17 * * MON-FRI
:周一至周五的9点到17点之间每小时执行任务
在线生成cron表达式的地址: 在线Cron表达式生成器
四、异步多线程实现定时任务
SpringBoot默认是单线程的定时任务,如果任务持续时间较长,就会将后续定时任务拖延,导致丢失任务。
在Spring Boot中,可以使用Spring的@Async
注解和TaskScheduler
来实现异步多线程的定时任务。下面是一个简单的例子:
4.1 首先,在Spring Boot的主类或配置类上添加@EnableAsync
注解以启用异步支持
@EnableAsync注解是SpringBoot中用于启动异步方法调用的注解
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling //开启定时任务
@EnableAsync //开启异步多线程支持
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
4.2 在定时任务上的方法上加上@Async注解(设置异步执行)
@Async 注解是 Spring 框架中用于声明一个方法是异步执行的。当你在一个类的方法上添加 @Async 注解时,Spring 会在执行该方法时开启一个新的线程来处理该方法,这样可以让你的应用程序同时执行多个任务,提高程序的效率。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class YourScheduledTask {
@Async
@Scheduled(fixedRate = 5000) // 每隔5秒执行一次任务
public void yourTask() {
// 执行你的任务逻辑
}
}
五、SpringBoot定时任务的实现原理
spring boot的定时任务底层其实就是使用线程池来实现的,其流程如下:
1.首先,Spring Boot 根据配置文件中的属性创建一个 TaskScheduler(如果没有自定义线程池会使用默认线程池ThreadPoolTaskScheduler)实例作为调度器,并设置线程池的相关属性,例如核心线程数、最大线程数、队列容量等。
2.当应用启动时,Spring Boot 会扫描所有被 @Scheduled 注解标记的方法,并将这些方法注册为定时任务。
3.当定时任务的触发条件满足时,调度器将从线程池中选择一个线程来执行任务。
4.执行任务时,调度器会通过 TaskExecutor(默认为 ThreadPoolTaskExecutor)实例来执行任务。它会从线程池中选择一个空闲的线程来执行被 @Scheduled 注解标记的方法。
4.执行完成后,线程将返回到线程池中等待下一次调度。