1. 概述

在这个教程中,我们将探讨Spring的任务调度机制——TaskScheduler及其预构建实现。然后,我们将深入研究不同的触发器用法。想要了解更多关于Spring中的调度,可以查阅这些文章:异步执行定时任务

Spring 3.0引入了TaskScheduler,它提供了一系列方法,用于在未来某个时间点执行任务。TaskScheduler还返回一个ScheduledFuture接口的表示对象,我们可以使用它来取消已安排的任务或检查它们是否已完成。

我们只需选择一个可运行的任务进行调度,并选择合适的调度策略即可。

2. ThreadPoolTaskScheduler

ThreadPoolTaskScheduler对于内部线程管理很有用,因为它将任务委托给ScheduledExecutorService,并实现了TaskExecutor接口。它能处理单个实例的异步潜在执行,以及@Async@Scheduled注解。

ThreadPoolTaskSchedulerConfig中定义ThreadPoolTaskSchedulerbean:

@Configuration
@ComponentScan(
  basePackages="com.baeldung.taskscheduler",
  basePackageClasses={ThreadPoolTaskSchedulerExamples.class})
public class ThreadPoolTaskSchedulerConfig {

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
        ThreadPoolTaskScheduler threadPoolTaskScheduler
          = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(5);
        threadPoolTaskScheduler.setThreadNamePrefix(
          "ThreadPoolTaskScheduler");
        return threadPoolTaskScheduler;
    }
}

配置的bean threadPoolTaskScheduler可以根据设置的5个线程池大小异步执行任务。

请注意,所有与ThreadPoolTaskScheduler相关的线程名称将带有ThreadPoolTaskScheduler前缀。

现在让我们实现一个简单的任务,然后安排它:

class RunnableTask implements Runnable{
    private String message;
    
    public RunnableTask(String message){
        this.message = message;
    }
    
    @Override
    public void run() {
        System.out.println(new Date()+" Runnable Task with "+message
          +" on thread "+Thread.currentThread().getName());
    }
}

现在我们可以安排taskScheduler在已知的时间后执行这个任务:

taskScheduler.schedule(
  new Runnabletask("Specific time, 3 Seconds from now"),
  new Date(System.currentTimeMillis + 3000)
);

taskScheduler将在当前时间之后的3秒准确地安排这个可运行任务。

现在让我们更深入地了解ThreadPoolTaskScheduler的调度机制。

3. 根据固定延迟安排可运行任务

我们可以使用两种简单方式安排一个固定的延迟:

3.1. 在上次安排执行后的固定延迟后安排任务

让我们配置一个任务,在上一次执行完成后延迟1000毫秒运行:

taskScheduler.scheduleWithFixedDelay(
  new RunnableTask("Fixed 1 second Delay"), 1000);

RunnableTask将在每次执行完成和下一次执行开始之间始终在1000毫秒后运行。

3.2. 在特定日期后的固定延迟后安排任务

让我们配置一个任务,在给定的开始时间后延迟固定时间运行:

taskScheduler.scheduleWithFixedDelay(
  new RunnableTask("Current Date Fixed 1 second Delay"),
  new Date(),
  1000);

RunnableTask将在指定的执行时间运行,包括@PostConstruct方法开始的时间,然后在1000毫秒延迟后。

4. 定时任务的固定速率安排

有两种简单方式安排以固定速率运行的可运行任务。

4.1. 按固定速率安排RunnableTask

让我们安排一个任务,每2000毫秒运行一次:

taskScheduler.scheduleAtFixedRate(
  new RunnableTask("Fixed Rate of 2 seconds") , 2000);

无论上次执行状态如何(可能仍在运行),下一个RunnableTask总是在2000毫秒后运行。

4.2. 从给定日期开始按固定速率安排RunnableTask

taskScheduler.scheduleAtFixedRate(new RunnableTask(
  "Fixed Rate of 2 seconds"), new Date(), 3000);

RunnableTask将在当前时间之后3000毫秒运行。

5. 使用CronTrigger进行调度

我们使用CronTrigger根据cron表达式安排任务:

CronTrigger cronTrigger 
  = new CronTrigger("10 * * * * ?");

我们可以使用提供的触发器按照特定的节奏或计划运行任务:

taskScheduler.schedule(new RunnableTask("Cron Trigger"), cronTrigger);

在这种情况下,RunnableTask将在每分钟的第10秒执行。

6. 使用PeriodicTrigger进行调度

让我们使用PeriodicTrigger固定延迟2000毫秒安排任务:

PeriodicTrigger periodicTrigger 
  = new PeriodicTrigger(2000, TimeUnit.MICROSECONDS);

配置的PeriodicTrigger bean用于在固定延迟2000毫秒后运行任务。

现在让我们用PeriodicTrigger安排RunnableTask

taskScheduler.schedule(
  new RunnableTask("Periodic Trigger"), periodicTrigger);

我们还可以配置PeriodicTrigger初始化为固定速率,而不是固定延迟。此外,我们可以设置首次安排任务的初始延迟,以给定的毫秒为单位。

我们只需要在periodicTrigger bean的返回语句之前添加两行代码:

periodicTrigger.setFixedRate(true);
periodicTrigger.setInitialDelay(1000);

我们使用setFixedRate方法以固定速率安排任务,而不是固定延迟。然后使用setInitialDelay方法设置首次可运行任务的初始延迟。

7. 总结

在这篇简短的文章中,我们学习了如何使用Spring对任务的支持进行任务调度。

我们演示了如何根据固定延迟、固定速率和特定触发器运行任务。

如往常一样,代码作为Maven项目可以在GitHub上找到:在这里


» 下一篇: JGit指南