面试题:SpringBoot 中如何实现定时任务 ?

在 Spring Boot 中,实现定时任务非常简单,主要依赖于 Spring 的 @Scheduled 注解和任务调度框架。以下是实现定时任务的几种常见方式:


1. 使用 @Scheduled 注解

@Scheduled 是 Spring 提供的一个注解,用于标记需要定时执行的方法。可以通过配置 cron 表达式、固定延迟或固定速率来定义任务的执行时间。

实现步骤:

  1. 在主类或配置类上添加 @EnableScheduling 注解,启用定时任务支持。
  2. 在需要定时执行的方法上添加 @Scheduled 注解。

示例代码:

import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@EnableScheduling
public class MyScheduledTasks {

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

    // 每次任务结束后延迟 3 秒执行
    @Scheduled(fixedDelay = 3000)
    public void taskWithFixedDelay() {
        System.out.println("Fixed Delay Task: " + System.currentTimeMillis());
    }

    // 使用 cron 表达式,每分钟的第 30 秒执行
    @Scheduled(cron = "30 * * * * ?")
    public void taskWithCronExpression() {
        System.out.println("Cron Task: " + System.currentTimeMillis());
    }
}

参数说明:

  • fixedRate:固定速率,单位毫秒。任务开始后,每隔指定时间执行一次。
  • fixedDelay:固定延迟,单位毫秒。任务结束后,延迟指定时间再执行下一次。
  • cron:Cron 表达式,用于定义复杂的调度规则。

Cron 表达式:

Cron 表达式由 6 或 7 个字段组成,格式为:秒 分 时 日 月 周 年(可选)。例如:

  • 0 * * * * ?:每分钟的第 0 秒执行。
  • 0 0 12 * * ?:每天中午 12 点执行。

2. 动态配置定时任务

如果需要动态调整定时任务的执行时间,可以通过编程方式实现。

实现步骤:

  1. 使用 ScheduledTaskRegistrar 注册定时任务。
  2. 通过自定义逻辑动态调整任务的执行时间。

示例代码:

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.stereotype.Component;

import java.util.concurrent.atomic.AtomicInteger;

@Component
@EnableScheduling
public class DynamicScheduledTask implements SchedulingConfigurer {

    private final AtomicInteger counter = new AtomicInteger(0);

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
            () -> {
                System.out.println("Dynamic Task: " + System.currentTimeMillis());
                counter.incrementAndGet();
            },
            triggerContext -> {
                // 动态调整 cron 表达式
                String cron = "0/" + counter.get() + " * * * * ?";
                return new CronTrigger(cron).nextExecutionTime(triggerContext);
            }
        );
    }
}

3. 使用 TaskScheduler

Spring 提供了 TaskScheduler 接口,可以通过编程方式调度任务。

示例代码:

import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.ScheduledFuture;

@Component
public class MyTaskScheduler {

    private final ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    private ScheduledFuture<?> future;

    @PostConstruct
    public void init() {
        taskScheduler.initialize();
        // 每 10 秒执行一次
        future = taskScheduler.schedule(
            () -> System.out.println("TaskScheduler Task: " + System.currentTimeMillis()),
            new CronTrigger("0/10 * * * * ?")
        );
    }

    public void cancelTask() {
        if (future != null) {
            future.cancel(true);
        }
    }
}

4. 使用 Quartz 调度框架

如果需要更强大的调度功能(如持久化任务、集群支持等),可以集成 Quartz 调度框架。

实现步骤:

  1. 添加 Quartz 依赖:
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>
  2. 配置 Quartz 任务和触发器。
  3. 使用 Scheduler 调度任务。

示例代码:

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetail jobDetail() {
        return JobBuilder.newJob(MyJob.class)
            .withIdentity("myJob")
            .storeDurably()
            .build();
    }

    @Bean
    public Trigger trigger() {
        return TriggerBuilder.newTrigger()
            .forJob(jobDetail())
            .withIdentity("myTrigger")
            .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
            .build();
    }
}
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Quartz Job: " + System.currentTimeMillis());
    }
}

5. 多线程定时任务

默认情况下,Spring 的定时任务是单线程执行的。如果需要并发执行任务,可以配置线程池。

示例代码:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class SchedulerConfig {

    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(5); // 设置线程池大小
        scheduler.setThreadNamePrefix("ScheduledTask-");
        return scheduler;
    }
}

总结

在 Spring Boot 中实现定时任务的方式包括:

  1. 使用 @Scheduled 注解(适合简单任务)。
  2. 动态配置定时任务(适合需要动态调整的任务)。
  3. 使用 TaskScheduler(适合编程式调度)。
  4. 使用 Quartz 框架(适合复杂调度需求)。
  5. 配置多线程定时任务(适合并发执行任务)。

根据具体需求选择合适的方式,可以轻松实现定时任务功能。

THE END
点赞6 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容