文章目录

  • 概述
  • TaskExecutor 接口
  • 概览
  • 简单分析
  • TaskScheduler 接口
  • 概览
  • 简单分析
  • Trigger 接口
  • 概览
  • 简单分析
  • 实现
  • Xml配置实现
  • 注解实现
  • 集成 SpringBoot (Java Config 实现)
  • 参考


概述

  1. 在 Spring 中提供的定时任务处理模块为 Spring Scheduler,主要包括 TaskExecutor、TaskScheduler、Trigger三个接口。
  2. TaskExecutor 是任务的执行器,允许异步执行多个任务。
  3. TaskScheduler 包含一些列调度任务的方法,以便在某个时间点运行。
  4. Trigger 触发器可以个根据过去的执行结果或者任意条件来确定执行时间

TaskExecutor 接口

概览

springquarzJob 查询调度中的任务 spring 任务调度框架_Scheduler

简单分析
  1. SyncTaskExecutor:同步实现,不建议使用,测试可用
  2. AsyncTaskExecutor:异步统一接口,主要是其实现被使用的较多。下面的都是其实现。
  3. SimpleAsyncTaskExecutor:不重用任何线程,而是为每个调用启动一个新的线程。支持并发限制,超出限制的任务会被阻塞,直到有空闲。
  4. ThreadPoolTaskExecutor:常用。spring自定义的标签 <task:executor> 用的就是这个类。内部使用的是JDK 的 ThreadPoolExecutor
  5. SimpleThreadPoolTaskExecutor:其实是 Quartz 的SimpleThreadPool 的子类,监听 Spring 的声明周期回调。
  6. WorkManagerTaskExecutor:该实现使用commonjWorkManager作为其后台实现。
  7. ConcurrentTaskExecutor:该实现是 java.util.concurrent.Executor对象的适配器,一般不会使用。如果觉得ThreadPoolTaskExecutor不够灵活,可以使用。

TaskScheduler 接口

概览

springquarzJob 查询调度中的任务 spring 任务调度框架_Scheduler_02

简单分析

TaskScheduler 接口是定时器的抽象,包含一组方法,用于指定任务执行的时间。Spring 主要提供两个实现TimerManagerTaskSchedulerThreadPoolTaskScheduler

  1. TaskScheduler 接口方法概览
public interface TaskScheduler {

	ScheduledFuture<?> schedule(Runnable task, Trigger trigger);

	ScheduledFuture<?> schedule(Runnable task, Date startTime);

	ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period);

	ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period);

	ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay);

	ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay);
}
  1. ThreadPoolTaskScheduler 是最常用的,spring自定义的标签 <task:scheduler> 使用的就是这个类。

Trigger 接口

概览

springquarzJob 查询调度中的任务 spring 任务调度框架_spring_03

简单分析
  1. TaskScheduler 接口中,可以使用 Trigger接口实现任务的执行。而Trigger是抽象了出发任务执行的触发器。Spring内置了CronTriggerPeriodicTrigger
  2. PeriodicTrigger 是直接按照给定的时间间隔触发任务执行
  3. CronTrigger 是使用Cron 表达式指定什么时候执行任务

实现

Spring Scheduler 使用非常简单,只依赖Spring,不需要其他依赖。

Xml配置实现

  1. 定义任务:最简单的一个java类,不需要任务其他
public class Task {

    public void doTask() {
        System.out.println("~~~ doTask 定时任务被执行 ~~~");
    }

    public void doTaskFixedDelay() {
        System.out.println("~~~ doTaskFixedDelay 定时任务被执行 ~~~");
    }
}
  1. 任务配置
# 定义任务的Bean
<bean id="task" class="com.learning.job.schedule.spring.xml.Task"/>

# xml 配置任务,指定 TaskScheduler
<task:scheduled-tasks scheduler="scheduler">
    # Cron 实现
    <task:scheduled ref="task" method="doTask" cron="*/10 * * * * ?"/>
    # 简单实现
    <task:scheduled ref="task" method="doTaskFixedDelay" fixed-delay="10"/>
</task:scheduled-tasks>
  1. TaskExecutor 配置。
  • <task:executor> 注册一个 ThreadPoolTaskExecutor 执行器。单独定义一个ThreadPoolTaskExecutor对象的bean,效果一样。
  • pool-size 队列默认执行队列是无限的,建议指定一个确定的数值
  • rejection-policy 拒绝策略,默认ABORT
  • keep-alive 超出线程池数量的线程完成任务后的存活时间,单位是秒
<task:executor id="executor" pool-size="10" queue-capacity="10" rejection-policy="ABORT" keep-alive="60"/>
  1. TaskScheduler 配置
  • <task:scheduler> 注册一个 ThreadPoolTaskScheduler 定时器
  • pool-size 属性设置线程池大小,默认是 1
<task:scheduler id="scheduler" pool-size="10"/>

注解实现

  1. 定义任务,并且配置任务
  • @Component 注册为一个Bean
  • @Scheduled 任务的配置实现,需要配置注解支持 <task:annotation-driven>。代替xml中的 <task:scheduled-tasks><task:scheduled> 配置。
@Component
public class Task {

    @Scheduled(cron = "*/10 * * * * ?")
    public void doTask() {
        System.out.println("~~~ doTask 定时任务被执行 ~~~");
    }

    @Scheduled(fixedDelay = 10L)
    public void doTaskFixedDelay() {
        System.out.println("~~~ doTaskFixedDelay 定时任务被执行 ~~~");
    }
}
  1. 配置注解支持
  • <task:annotation-driven> 配置注解 @Scheduled@Async的支持。其实在JavaConfig中EnableSchedulingEnableAsync代替。
  • scheduler 配置自定义的 TaskScheduler
  • executor 配置自定义的 TaskExecutor
  • proxy-target-class 是否使用 CGLIB 。默认是使用 Java interface-based proxies
  • mode 选择Aop 的实现,主要是 proxy(默认) 或者 aspectj
  • exception-handler 异常的处理,默认是SimpleAsyncUncaughtExceptionHandler,简单记录日志,可以自定义实现。
# 注解支持配置 
<task:annotation-driven scheduler="scheduler" executor="executor" proxy-target-class="true" mode="proxy" exception-handler="exceptionHandler"/>

# 异常处理
<bean id="exceptionHandler" class="org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler"/>
  1. 配置TaskExecutorTaskScheduler
<task:scheduler id="scheduler" pool-size="10"/>
<task:executor id="executor" pool-size="10" queue-capacity="10" rejection-policy="ABORT"/>

集成 SpringBoot (Java Config 实现)

  1. 定义任务
@Component
public class Task {

    @Scheduled(cron = "*/10 * * * * ?")
    public void doTask() {
        System.out.println("~~~ doTask 定时任务被执行 ~~~");
    }

    @Scheduled(fixedDelay = 1000L)
    public void doTaskFixedDelay() {
        System.out.println("~~~ doTaskFixedDelay 定时任务被执行 ~~~");
    }
    /**
     * 手动添加
     */
    public void doTask2() {
        System.out.println("~~~ doTask2 定时任务被执行 ~~~");
    }
}
  1. 任务的配置,使用 JavaConfig 代替XMl中配置,原则上来说,如果不需要自定义,只需要配置 @EnableScheduling 即可实现功能。
  • @EnableScheduling 代替 <task:annotation-driven>中用于@Scheduled的功能。@Async 的使用需要使用@EnableAsync注解
  • SchedulingConfigurer 全局自定义配置需要实现该接口,重写 configureTasks()方法。如果 @Async 的配置需要实现AsyncConfigurer
  • ScheduledTaskRegistrar 任务注册。支持添加 TaskExecutorTaskScheduler、执行任务等。
@Configuration
@EnableScheduling
public class AppConfig implements SchedulingConfigurer {

    @Autowired
    Task task;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        # 添加自定义 `TaskExecutor`、`TaskScheduler`
        taskRegistrar.setScheduler(taskExecutor());
        // taskRegistrar.setScheduler();
        
        #  手动添加执行任务
        taskRegistrar.addFixedDelayTask(() -> task.doTask2(), 5000L);
    }

    # 定义 TaskExecutor
    @Bean
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(100);
    }
}

参考

  1. 源码地址 Learning_Job_Schedule