Springboot 开发之 Scheduled 定时任务详解及实战

引言

Spring Boot中的@Scheduled注解用于配置定时任务,使得方法可以按照规定的时间间隔或特定的时间点定时执行。下面将详细解释@Scheduled注解的使用方法及其实战应用。

一、@Scheduled注解的基本用法

@Scheduled注解可以应用于方法上,并通过不同的参数来指定任务的执行时间、循环周期等。它主要支持以下几种时间配置方式:

  • fixedRate:表示固定频率执行,即上一次开始执行时间点后,再经过固定的时间间隔才执行下一次任务。例如,@Scheduled(fixedRate = 5000)表示每隔5秒执行一次任务。
  • fixedDelay:表示固定延迟时间执行,即上一次执行结束后,再经过固定的时间间隔才执行下一次任务。例如,@Scheduled(fixedDelay = 10000)表示在上一次任务执行完毕后,延迟10秒再执行下一次任务。
  • initialDelay:表示初始延迟时间,即在Spring容器启动后,需要等待一段时间才开始执行定时任务。它可以与fixedRate或fixedDelay一起使用。
  • cron:使用Cron表达式配置定时任务的执行时间。Cron表达式是一种强大的时间配置方式,可以指定复杂的执行计划。例如,@Scheduled(cron = “0 0 12 * * ?”)表示每天中午12点执行任务。

cron 表达式在线解析可以参考 https://cron.qqe2.com/

二、@Scheduled注解的实战应用

1. 启用定时任务

要在Spring Boot项目中启用定时任务,首先需要在启动类上添加@EnableScheduling注解。这个注解会开启Spring的任务调度功能,使得被@Scheduled注解的方法能够按照指定的时间规则执行。


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

2. 创建定时任务

接下来,可以创建一个定时任务类,并在其中定义被@Scheduled注解的方法。这个类通常会被@Component注解标记,以便Spring容器能够扫描到它。

@Component  
public class ScheduledTasks {  
  
    @Scheduled(fixedRate = 5000)  
    public void fixedRateTask() {  
        System.out.println("Fixed rate task - " + System.currentTimeMillis() / 1000);  
    }  
  
    @Scheduled(fixedDelay = 10000)  
    public void fixedDelayTask() {  
        System.out.println("Fixed delay task - " + System.currentTimeMillis() / 1000);  
    }  
  
    @Scheduled(cron = "0 0 1 * * ?")  
    public void cronTask() {  
        System.out.println("Cron task - " + System.currentTimeMillis() / 1000);  
    }  
}

3. 异步执行定时任务

Spring支持异步执行定时任务,只需在方法上添加@Async注解,并确保在配置类上添加@EnableAsync注解。

@Configuration
@EnableAsync
@EnableScheduling
public class AsyncScheduleConfig {
    // 配置类内容
}

@Component
public class AsyncScheduledTasks {

    @Async
    @Scheduled(fixedRate = 10000)
    public void asyncTask() {
        System.out.println("Async Task - 异步执行的定时任务");
    }
}

4. 注意事项

  • 被@Scheduled注解的方法不能有返回值,且必须为public
  • 如果任务的执行时间过长,超过了设定的时间间隔(如fixedRate或fixedDelay),Spring会等待当前任务完成后,再开始下一个任务的执行,这可能会导致任务堆积。
  • 如果任务需要访问数据库等资源,需要注意线程安全问题。
  • 在集群环境中,需要考虑分布式锁等机制,避免多个节点同时执行同一个任务

三、解决@Scheduled任务不执行的问题

如果@Scheduled任务没有按预期执行,可能是由以下几个原因造成的:

  • Cron表达式设置错误:检查Cron表达式是否正确无误。
  • 线程池配置问题:如果任务线程池已满,新的任务可能无法执行。可以通过调整线程池配置来解决这个问题。
  • 任务方法异常:任务方法中可能出现了异常,导致任务执行失败。可以在任务方法中添加异常处理逻辑。
  • Spring容器未扫描到@Scheduled注解:确保在启动类上添加了@EnableScheduling注解,并且Spring容器能够扫描到包含@Scheduled注解的类。

四、@Scheduled的多线程使用

1. @Scheduled多线程机制

在Spring Boot中,@Scheduled注解是基于Java的ThreadPoolExecutorScheduledThreadPoolExecutor实现的。Spring Boot会创建一个ScheduledThreadPoolExecutor线程池,并将定时任务添加到该线程池中等待执行。在指定的时间到来后,线程池会为定时任务分配一个线程来执行。

2. @Scheduled加入线程池处理定时任务

为了避免多线程问题,可以将@Scheduled任务交给线程池进行处理。以下是两种常见的方法:

(1) 使用@EnableScheduling + @Configuration配置ThreadPoolTaskScheduler


@Configuration
@EnableScheduling
public class TaskSchedulerConfig {
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);  // 设置线程池大小
        scheduler.initialize();
        return scheduler;
    }
}

在这个配置中,通过ThreadPoolTaskScheduler创建了一个线程池,并设置了线程池的大小。

(2) 使用ThreadPoolTaskExecutor

@Configuration
@EnableScheduling
public class TaskExecutorConfig {
    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);  // 设置核心线程池大小
        executor.setMaxPoolSize(50);   // 设置最大线程池大小
        executor.setQueueCapacity(1000);  // 设置队列容量
        executor.setKeepAliveSeconds(60);  // 设置线程存活时间
        executor.setThreadNamePrefix("task-executor-");  // 设置线程名称前缀
        return executor;
    }
}

在这个配置中,通过ThreadPoolTaskExecutor创建了一个线程池,并配置了线程池的核心参数。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值