spring task使用

Spring Task 简介

Spring Task 是 Spring 框架原生自带的任务调度框架,它犹如一把瑞士军刀,为开发者提供了丰富多样的功能,助力轻松创建和管理定时任务。相较于其他一些第三方任务调度框架,Spring Task 最大的优势在于其与 Spring 生态系统的无缝集成。这意味着开发者能够在 Spring 应用中自如地运用依赖注入、事务管理等强大特性,使得代码的编写过程更加流畅,后期维护也更为便捷。例如,在一个电商系统中,我们可以利用 Spring Task 定时更新商品库存信息,同时借助依赖注入获取商品服务层的实例,实现业务逻辑的高效处理。

添加依赖

非 Spring Boot 的 Spring 项目中,需要添加 spring-context 依赖:

Spring Boot 项目中无需添加依赖

复制代码
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
</dependency>

开启定时任务

若要在 Spring 项目中启用定时任务功能,首要步骤是在配置类或主启动类上添加@EnableScheduling注解。

复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
public class AppConfig {
    // 配置类中的其他配置,如数据源配置、Bean的定义等
}

在上述代码中,AppConfig类通过添加@Configuration注解表明这是一个配置类,而@EnableScheduling注解则通知 Spring 容器开始扫描并注册所有带有定时任务注解的方法,为后续的定时任务执行做好准备。

基于 Spring Boot 主启动类

复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

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

对于 Spring Boot 项目,在主启动类Application上添加@SpringBootApplication注解,它整合了@Configuration、@EnableAutoConfiguration和@ComponentScan等多个注解的功能,而@EnableScheduling注解的加入则开启了定时任务的支持。当应用启动时,Spring 容器会自动扫描整个项目,识别并注册符合条件的定时任务。

添加了这个注解后,Spring 容器就如同一个敏锐的观察者,会自动扫描并注册所有带有定时任务注解的方法,为后续定时任务的执行搭建好了舞台。

@Scheduled 注解实现定时任务

在 Spring Task 的工具库中,最常用的定时任务定义方式当属使用@Scheduled注解。我们只需将这个注解添加到想要定时执行的方法上,Spring 就会严格按照我们指定的规则,如同忠诚的守护者一般,在合适的时间点准时调用这个方法。

例如,创建一个简单的定时任务,每隔 5 秒输出一条日志,记录系统的运行状态,代码如下:

复制代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class SimpleTask {
    private static final Logger logger = LoggerFactory.getLogger(SimpleTask.class);

    @Scheduled(fixedRate = 5000)
    public void executeTask() {
        logger.info("定时任务执行了!当前时间为:{}", System.currentTimeMillis());
    }
}

在上述代码中,@Scheduled(fixedRate = 5000)表示这个方法会以固定的速率执行,每 5000 毫秒(即 5 秒)执行一次。每次任务执行时,都会在日志中记录下 "定时任务执行了!" 以及当前的时间戳,方便开发者追踪任务的执行情况。

执行策略

cron 表达式

cron表达式堪称任务执行时间定义的魔法咒语,它以一种极为灵活且强大的方式来精准控制任务的执行时间。它由 6 或 7 个空格分隔的时间字段组成,从左到右分别表示秒、分、时、日、月、周以及年(年字段为可选)。

例如,要在每天的凌晨 2 点整执行任务,对数据库进行日常备份,确保数据的完整性,配置如下:

复制代码
@Scheduled(cron = "0 0 2 * * *")
public void dailyTask() {
    // 数据库备份逻辑,例如调用数据库备份工具或执行SQL语句
}

下面是一些常用的cron表达式示例,帮助开发者更好地理解和运用:

  • 0 0 12 * *?:每天中午 12 点整执行,适用于在中午进行数据统计或报表生成的场景。
  • 0 15 10 * *?:每天上午 10 点 15 分执行,可用于在工作时间开始时更新系统数据或发送通知。
  • 0 0/5 * * *?:每隔 5 分钟执行一次,常用于实时数据监控或缓存更新的场景。

fixedDelay

fixedDelay表示上一次任务执行完毕后,间隔指定的时间再执行下一次任务。例如,设置fixedDelay = 3000,意味着上一次任务执行完成后,系统会耐心等待 3 秒,然后再启动下一次任务。这种策略适用于任务执行时间不固定,但希望每次执行之间有一定间隔的场景,比如在数据采集任务中,每次采集完成后,需要一定时间处理数据,处理完后再进行下一次采集。

复制代码
@Scheduled(fixedDelay = 3000)
public void taskWithFixedDelay() {
    // 数据采集或其他任务执行逻辑
}

fixedRate

fixedRate表示按照固定的时间间隔执行任务,无论上一次任务是否执行完毕。例如,设置fixedRate = 5000,表示每隔 5 秒就会启动一次任务,如同一个精准的时钟,不管前一次任务的状态如何,都会按时触发下一次任务。这种策略适用于需要持续周期性执行的任务,比如定时向服务器发送心跳包以保持连接。

复制代码
@Scheduled(fixedRate = 5000)
public void taskWithFixedRate() {
    // 发送心跳包或其他周期性任务执行逻辑
}

initialDelay

initialDelay用于指定在应用启动后,延迟多长时间再执行第一次任务。它通常与fixedRate或fixedDelay一起使用,为任务的首次执行提供了灵活的控制。

例如,应用启动后延迟 2 秒,然后每隔 5 秒执行一次任务,可用于在系统初始化完成后,再开始执行周期性任务。

复制代码
@Scheduled(initialDelay = 2000, fixedRate = 5000)
public void taskWithInitialDelay() {
    // 系统初始化后的周期性任务执行逻辑
}

异步使用

在某些复杂的业务场景下,我们可能期望定时任务能够异步执行,避免阻塞主线程,确保系统的高并发性能和响应速度。Spring Task 充分考虑到了这一需求,提供了完善的异步执行支持。

首先,需要在配置类中启用异步任务支持,添加@EnableAsync注解:

复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
@EnableAsync
public class AppConfig {
    // 配置类中的其他配置,如线程池配置等
}

在上述代码中,@EnableAsync注解告诉 Spring 容器开启异步任务的功能,允许方法在独立的线程中执行。同时,我们还可以在配置类中进一步配置线程池的参数,如线程池的大小、最大线程数等,以优化异步任务的执行效率。

然后,在需要异步执行的定时任务方法所在的类上添加@Async注解:

复制代码
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@Async
public class AsyncTask {
    @Scheduled(fixedRate = 5000)
    public void asyncExecuteTask() {
        // 异步任务执行逻辑,例如调用远程服务或进行复杂计算
    }
}

当asyncExecuteTask方法被调用时,它会在一个单独的线程池中执行,如同在后台默默工作的助手,不会干扰主线程的正常运行,从而确保系统在处理定时任务的同时,能够高效地响应其他用户请求。

相关推荐
考虑考虑41 分钟前
JDK9中的dropWhile
java·后端·java ee
想躺平的咸鱼干1 小时前
Volatile解决指令重排和单例模式
java·开发语言·单例模式·线程·并发编程
hqxstudying1 小时前
java依赖注入方法
java·spring·log4j·ioc·依赖
·云扬·1 小时前
【Java源码阅读系列37】深度解读Java BufferedReader 源码
java·开发语言
春生野草2 小时前
关于SpringMVC的整理
spring
martinzh2 小时前
Spring AI 项目介绍
后端
Bug退退退1232 小时前
RabbitMQ 高级特性之重试机制
java·分布式·spring·rabbitmq
小皮侠2 小时前
nginx的使用
java·运维·服务器·前端·git·nginx·github
前端付豪3 小时前
20、用 Python + API 打造终端天气预报工具(支持城市查询、天气图标、美化输出🧊
后端·python
爱学习的小学渣3 小时前
关系型数据库
后端