java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot @Scheduled定时任务

SpringBoot项目使用@Scheduled注解实现定时任务的方法

作者:Eternitysy

文章介绍了在SpringBoot项目中使用@Scheduled注解实现定时任务的三种方式:基于注解、基于接口和基于注解设定多线程定时任务,详细讲解了@Scheduled注解的使用方法、各个参数以及如何配置动态定时任务和多线程定时任务,感兴趣的朋友一起看看吧

SpringBoot项目【使用@Scheduled注解实现定时任务】

使用SpringBoot创建定时任务目前主要有以下三种创建方式:

1、基于注解(@Scheduled)

- 最简单直接
2、基于接口(SchedulingConfigurer)

- 适于实际使用中从数据库中读取指定时间来动态执行定时任务
3、基于注解设定多线程定时任务

1. 基于注解(@Scheduled)

1.1 @Scheduled 注解和 @EnableScheduling 注解的使用

基于注解@Scheduled默认为单线程,开启多个任务时,任务的执行会受上一个任务执行时间影响

@EnableScheduling注解: 在配置类上使用,开启计划任务的支持(类上)。

@Scheduled注解: 来声明这是一个任务,包括 cron,fixDelay,fixRate 等类型(方法上,需先开启计划任务的支持)。

【示例】SpringBoot项目中使用@Scheduled注解和@EnableScheduling注解实现定时任务。

(1)开启定时任务

SpringBoot 项目在项目启动类上添加 @EnableScheduling 注解即可开启定时任务管理。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling //开启定时任务
public class ScheduledDemoApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(ScheduledDemoApplication.class, args);
    }
}

(2)创建定时任务

创建定时任务,并使用 @Scheduled 注解。

package com.pjb.Schedule;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * 定时任务的使用
 * @author pan_junbiao
 **/
@Component
public class Task
{
    @Scheduled(cron="0/5 * *  * * ? ")   //每5秒执行一次
    public void execute(){
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置日期格式
        System.out.println("欢迎访问 pan_junbiao的博客 " + df.format(new Date()));
    }
}

1.2 @Scheduled 注解各参数讲解

@Scheduled 注解具有多个参数,以下是常用的几个参数:

cron

接收一个 cron 表达式。cron 表达式由六个或七个域组成,常见的格式如下:

css
复制编辑
[秒] [分] [小时] [日] [月] [周] [年]

序号说明是否必填允许填写的值允许的通配符
10-59, - * /
20-59, - * /
3小时0-23, - * /
41-31, - * ? / L W
51-12 or JAN-DEC, - * /
61-7 or SUN-SAT, - * ? / L #
7空或1970-2099, - * /

通配符说明:

? 表示不指定值。使用的场景为不需要关心当前设置这个字段的值。例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为"?" 具体设置为 0 0 0 10 * ?

-表示区间。例如 在小时上设置 “10-12”,表示 10,11,12点都会触发。

, 表示指定多个值,例如在周字段上设置 “MON,WED,FRI” 表示周一,周三和周五触发

/ 用于递增触发。如在秒上面设置"5/15" 表示从5秒开始,每增15秒触发(5,20,35,50)。在月字段上设置’1/3’所示每月1号开始,每隔三天触发一次。

L 表示最后的意思。在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会依据是否是润年[leap]), 在周字段上表示星期六,相当于"7"或"SAT"。如果在"L"前加上数字,则表示该数据的最后一个。例如在周字段上设置"6L"这样的格式,则表示“本月最后一个星期五"

W 表示离指定日期的最近那个工作日(周一至周五). 例如在日字段上设置"15W",表示离每月15号最近的那个工作日触发。(注,“W"前只能设置具体的数字,不允许区间”-")

常用示例:

定时任务表达式描述
0 0 12 * * ?每天12点触发
0 15 10 ? * *每天10点15分触发
0 15 10 * * ?每天10点15分触发
0 15 10 * * ? *每天10点15分触发
0 15 10 * * ? 20252025年每天10点15分触发
0 * 14 * * ?每天下午的 2点到2点59分每分触发
0 0/5 14 * * ?每天下午的 2点到2点59分(整点开始,每隔5分触发)
0 0/5 14,18 * * ?每天下午的 2点到2点59分(整点开始,每隔5分触发)每天下午的 18点到18点59分(整点开始,每隔5分触发)
0 0-5 14 * * ?每天下午的 2点到2点05分每分触发
0 10,44 14 ? 3 WED3月分每周三下午的 2点10分和2点44分触发
0 15 10 ? * MON-FRI从周一到周五每天上午的10点15分触发
0 15 10 15 * ?每月15号上午10点15分触发
0 15 10 L * ?每月最后一天的10点15分触发
0 15 10 ? * 6L每月最后一周的星期五的10点15分触发
0 15 10 ? * 6L 2022-2025从2022年到2025年每月最后一周的星期五的10点15分触发
0 15 10 ? * 6#3每月的第三周的星期五开始触发
0 0 12 1/5 * ?每月的第一个中午开始每隔5天触发一次
0 11 11 11 11 ?每年的11月11号 11点11分触发(光棍节)

其他常用

2. 动态定时任务:基于接口(SchedulingConfigurer)

2.1 创建数据库表

在 MySQL 数据库中创建一个 cron 表,存储定时任务的 cron 表达式:

DROP TABLE IF EXISTS cron;
CREATE TABLE cron (
    cron_id VARCHAR(30) NOT NULL PRIMARY KEY,
    cron VARCHAR(30) NOT NULL
);
INSERT INTO cron VALUES ('1', '0/5 * * * * ?');

2.2 添加 MyBatis 依赖

pom.xml 中添加 MyBatis 和 MySQL 的 JDBC 依赖:

<!-- MyBatis与SpringBoot整合依赖 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>
<!-- MySQL的JDBC数据库驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.20</version>
</dependency>

2.3 创建定时任务配置类

package com.pjb.config;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
/**
 * 动态定时任务配置类
 * @author pan_junbiao
 **/
@Configuration
@EnableScheduling
public class DynamicScheduleConfigurer implements SchedulingConfigurer {
    @Mapper
    public interface CronMapper {
        @Select("select cron from cron limit 1")
        public String getCron();
    }
    @Autowired
    CronMapper cronMapper;
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                () -> System.out.println("欢迎访问 pan_junbiao的博客: " + LocalDateTime.now().toLocalTime()),
                triggerContext -> {
                    String cron = cronMapper.getCron();
                    if (StringUtils.isEmpty(cron)) {
                        // 错误处理
                    }
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                }
        );
    }
}

3. 基于注解设定多线程定时任务

通过 @Async 注解开启多线程定时任务,解决多个任务执行时相互影响的问题。

创建多线程定时任务

package com.pjb.Task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
 * 基于注解设定多线程定时任务
 * @author pan_junbiao
 */
@Component
@EnableScheduling   // 开启定时任务
@EnableAsync        // 开启多线程
public class MultithreadScheduleTask {
    @Async
    @Scheduled(fixedDelay = 1000)  // 间隔1秒
    public void first() throws InterruptedException {
        System.out.println("第一个定时任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());
        Thread.sleep(1000 * 10);
    }
    @Async
    @Scheduled(fixedDelay = 2000)
    public void second() {
        System.out.println("第二个定时任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());
    }
}

注意

由于 @Scheduled 默认是单线程模式,开启多个定时任务时任务的执行顺序会受前一个任务的执行时间影响。通过 @Async 注解,我们可以解决这个问题,使多个定时任务并行执行。

通过以上三种方式,Spring Boot 提供了灵活的定时任务支持,可以根据项目需求选择合适的实现方式。

到此这篇关于SpringBoot项目使用@Scheduled注解实现定时任务的文章就介绍到这了,更多相关SpringBoot @Scheduled定时任务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文