Spring Task 使用详解

在应用开发中,定时任务扮演着至关重要的角色,例如定时数据同步、定时邮件发送、定时清理缓存等。Spring Framework 提供了一个强大而灵活的定时任务框架------Spring Task,它可以帮助我们轻松地实现各种定时任务,而无需依赖复杂的第三方库。本文将深入探讨 Spring Task 的使用方法,并结合 Spring Boot 项目进行演示,涵盖 @Scheduled 注解的多种用法、Cron 表达式的详细解释、SchedulingConfigurer 接口的灵活配置以及异步任务的处理。

1. Spring Task 简介

Spring Task 基于 @Scheduled 注解和 ScheduledExecutorService 线程池,提供了两种主要方式来实现定时任务:

  • 基于注解 @Scheduled: 简洁易用,适用于大多数场景。通过在方法上添加 @Scheduled 注解,并配置 cron 表达式、fixedRate、fixedDelay 或 fixedRateString/fixedDelayString 参数,即可实现定时执行。

  • 基于接口 SchedulingConfigurer: 提供更灵活的配置方式,可以自定义线程池,适用于对任务调度有更高要求的场景,例如需要控制并发线程数、设置线程池队列大小等。

2. 基于 @Scheduled 注解的使用

2.1 添加依赖 (Spring Boot 项目通常无需额外添加,因为自带该依赖)

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

***Spring Boot 项目中无需添加依赖***

XML 复制代码
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
</dependency>
2.2 开启定时任务支持

在 Spring Boot 项目的配置类上添加 @EnableScheduling 注解:

java 复制代码
@SpringBootApplication
@EnableScheduling   //开启定时任务
public class MyApplication {
    // ...
}
2.3 创建定时任务

采用注解方式,主要是cron表达式

java 复制代码
@Component
public class ScheduledTasks {

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    // 每5秒执行一次
    @Scheduled(fixedRate = 5000)
    public void fixedRateTask() {
        System.out.println("Fixed Rate Task : " + dateFormat.format(new Date()));
    }

    // 每分钟执行一次
    @Scheduled(cron = "0 * * * * ?") // 注意:此处纠正了cron表达式
    public void cronTask() {
        System.out.println("Cron Task : " + dateFormat.format(new Date()));
    }

    // 上一次任务执行完成后,延迟10秒再执行
    @Scheduled(fixedDelay = 10000)
    public void fixedDelayTask() {
        System.out.println("Fixed Delay Task : " + dateFormat.format(new Date()));
        try {
            Thread.sleep(5000); // 模拟任务执行时间
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 使用字符串配置,更灵活,支持占位符
    @Scheduled(fixedRateString = "${my.fixedRate}") // application.properties 中配置 my.fixedRate=6000
    public void fixedRateStringTask() {
        System.out.println("Fixed Rate String Task : " + dateFormat.format(new Date()));
    }
}
2.4 Cron 表达式详解

Cron 表达式由6或7个字段组成,用空格分隔,分别表示:

java 复制代码
秒   分   时   日   月   周   年
  • 秒 (0-59)

  • 分 (0-59)

  • 时 (0-23)

  • 日 (1-31)

  • 月 (1-12)

  • 周 (0-7) (0 和 7 都代表星期天)

  • 年20XX

举例:(周 和 日 不能同时出现,若一定要同时出现,则其中一个必须为" ?",因为会产生冲突)

特殊字符:

  • *:代表所有可能的值

  • ?:不指定值,用于日和周字段,表示不关心具体值

  • -:指定一个范围

  • ,:列出多个值

  • /:指定增量

  • L:表示最后一个,例如月的最后一个星期日

  • W:表示最接近指定日期的工作日

  • #:表示第几个,例如周的第几个星期日

更详细的 Cron 表达式示例:

  • 0 0 12 * * ?:每天中午12点触发

  • 0 15 10 ? * MON-FRI:周一至周五每天上午10:15触发

  • 0 0/5 * * * ?:每5分钟触发

  • 0 0 1,12 * * ?:每天凌晨1点和中午12点触发

  • 0 10 1 * * 6L:每个月的最后一个星期五上午10:10触发

  • 0 0 10 ? * 2#3:每个月的第三个星期二上午10:00触发

3. 基于 SchedulingConfigurer 接口的使用

java 复制代码
@Configuration
public class TaskSchedulerConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean(destroyMethod="shutdown")
    public Executor taskExecutor() {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5); // 设置线程池大小为5
        executor.setRemoveOnCancelPolicy(true); // 设置取消策略
        executor.setThreadNamePrefix("MyScheduled-"); // 设置线程名前缀
        return executor;
    }
}

4. 异步任务

为了避免阻塞主线程,可以将耗时的定时任务设置为异步执行。

java 复制代码
@Component
public class AsyncScheduledTasks {

    @Async
    @Scheduled(fixedRate = 5000)
    public void asyncTask() {
        // ... 执行耗时操作 ...
    }
}

@Configuration
@EnableAsync // 开启异步任务支持
public class AsyncConfig implements AsyncConfigurer {
    // ... 配置异步任务线程池 ...
}

5. 简单使用示例

编写MyTask 定时任务

5.1 首先启动类添加注解 @EnableScheduling
5.2 编写task定时方法
java 复制代码
/**
 * 自定义定时任务类
 */
@Component
@Slf4j
public class MyTask {

    /**
     * 定时任务 每隔5秒触发一次
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void executeTask(){
        log.info("定时任务开始执行:{}",new Date());
    }
}

运行:每隔五秒执行定时任务

6. 总结

Spring Task 提供了强大且灵活的定时任务管理功能,@Scheduled 注解的便捷性和 SchedulingConfigurer 接口的灵活性可以满足各种定时任务的需求。结合异步任务处理,可以进一步优化应用性能。

希望本文能帮助各位看官更深入地理解和使用 Spring Task,在你的项目中优雅地实现定时任务。 感谢各位看官的观看,下期见,谢谢~

相关推荐
战族狼魂1 分钟前
CSGO 皮肤交易平台后端 (Spring Boot) 代码结构与示例
java·spring boot·后端
xyliiiiiL1 小时前
ZGC初步了解
java·jvm·算法
杉之1 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
hycccccch2 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
bobz9653 小时前
k8s 怎么提供虚拟机更好
后端
zhuyixiangyyds3 小时前
day21和day22学习Pandas库
笔记·学习·pandas
每次的天空3 小时前
Android学习总结之算法篇四(字符串)
android·学习·算法
bobz9653 小时前
nova compute 如何创建 ovs 端口
后端
天天向上杰3 小时前
面基JavaEE银行金融业务逻辑层处理金融数据类型BigDecimal
java·bigdecimal
请来次降维打击!!!3 小时前
优选算法系列(5.位运算)
java·前端·c++·算法