Spring 的任务调度机制概述

Spring 框架提供了强大的任务调度功能,主要有两种方式来实现任务调度:基于注解和基于 XML 配置。

1. 基于注解的任务调度

Spring 提供了 @Scheduled 注解,允许你方便地在方法上指定任务的执行时间。使用这种方式,需要在配置类上添加 @EnableScheduling 注解来启用调度功能。

下面是一个简单的示例:

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

@Component
public class ScheduledTasks {

    // 固定延迟,任务执行完成后等待 5 秒再执行下一次
    @Scheduled(fixedDelay = 5000) 
    public void performTaskWithFixedDelay() {
        System.out.println("Task executed with fixed delay at " + System.currentTimeMillis());
    }

    // 固定速率,每隔 3 秒执行一次任务
    @Scheduled(fixedRate = 3000) 
    public void performTaskWithFixedRate() {
        System.out.println("Task executed with fixed rate at " + System.currentTimeMillis());
    }

    // 使用 Cron 表达式,每天凌晨 2 点执行任务
    @Scheduled(cron = "0 0 2 * * ?") 
    public void performTaskWithCron() {
        System.out.println("Task executed with cron expression at " + System.currentTimeMillis());
    }
}

配置类:

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
public class AppConfig {
    // 配置类可以添加其他配置
}

2. 基于 XML 配置的任务调度

在 Spring 中,也可以通过 XML 配置来实现任务调度。以下是一个简单的 XML 配置示例:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/task
                           http://www.springframework.org/schema/task/spring-task.xsd">

    <task:annotation-driven/>

    <bean id="scheduledTasks" class="com.example.ScheduledTasks"/>

    <task:scheduler id="taskScheduler" pool-size="10"/>

    <task:scheduled-tasks scheduler="taskScheduler">
        <task:scheduled ref="scheduledTasks" method="performTaskWithFixedRate" fixed-rate="3000"/>
    </task:scheduled-tasks>
</beans>

实现动态任务调度

动态任务调度意味着可以在运行时添加、修改或删除任务。Spring 提供了 ThreadPoolTaskScheduler 类来实现动态任务调度。

以下是一个实现动态任务调度的示例:

DynamicTaskSchedulerExample.java

import org.springframework.scheduling.TaskScheduler;
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.ScheduledFuture;

@Component
@EnableScheduling
public class DynamicTaskSchedulerExample implements SchedulingConfigurer {

    private TaskScheduler taskScheduler;
    private ScheduledFuture<?> scheduledFuture;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskScheduler = taskRegistrar.getScheduler();
    }

    public void startTask(String cronExpression) {
        if (scheduledFuture != null) {
            scheduledFuture.cancel(true);
        }
        scheduledFuture = taskScheduler.schedule(() -> {
            System.out.println("Dynamic task executed at " + System.currentTimeMillis());
        }, new CronTrigger(cronExpression));
    }

    public void stopTask() {
        if (scheduledFuture != null) {
            scheduledFuture.cancel(true);
        }
    }
}    

代码解释

  • DynamicTaskSchedulerExample 类实现了 SchedulingConfigurer 接口,重写了 configureTasks 方法,获取 TaskScheduler 实例。
  • startTask 方法用于启动一个新的任务,可以传入 Cron 表达式来指定任务的执行时间。如果之前已经有任务在运行,会先取消之前的任务。
  • stopTask 方法用于停止当前正在运行的任务。

你可以在其他类中注入 DynamicTaskSchedulerExample 类,并调用 startTaskstopTask 方法来动态管理任务调度。例如:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TaskController {

    @Autowired
    private DynamicTaskSchedulerExample dynamicTaskScheduler;

    @GetMapping("/startTask")
    public String startTask(@RequestParam String cronExpression) {
        dynamicTaskScheduler.startTask(cronExpression);
        return "Task started with cron expression: " + cronExpression;
    }

    @GetMapping("/stopTask")
    public String stopTask() {
        dynamicTaskScheduler.stopTask();
        return "Task stopped";
    }
}

通过上述代码,你可以在运行时动态地启动和停止任务,并且可以根据需要修改任务的执行时间。