文章目录
- 概述
- TaskExecutor 接口
- 概览
- 简单分析
- TaskScheduler 接口
- 概览
- 简单分析
- Trigger 接口
- 概览
- 简单分析
- 实现
- Xml配置实现
- 注解实现
- 集成 SpringBoot (Java Config 实现)
- 参考
概述
- 在 Spring 中提供的定时任务处理模块为 Spring Scheduler,主要包括 TaskExecutor、TaskScheduler、Trigger三个接口。
- TaskExecutor 是任务的执行器,允许异步执行多个任务。
- TaskScheduler 包含一些列调度任务的方法,以便在某个时间点运行。
- Trigger 触发器可以个根据过去的执行结果或者任意条件来确定执行时间
TaskExecutor 接口
概览
简单分析
-
SyncTaskExecutor
:同步实现,不建议使用,测试可用 -
AsyncTaskExecutor
:异步统一接口,主要是其实现被使用的较多。下面的都是其实现。 -
SimpleAsyncTaskExecutor
:不重用任何线程,而是为每个调用启动一个新的线程。支持并发限制,超出限制的任务会被阻塞,直到有空闲。 -
ThreadPoolTaskExecutor
:常用。spring自定义的标签<task:executor>
用的就是这个类。内部使用的是JDK 的ThreadPoolExecutor
。 -
SimpleThreadPoolTaskExecutor
:其实是 Quartz 的SimpleThreadPool
的子类,监听 Spring 的声明周期回调。 -
WorkManagerTaskExecutor
:该实现使用commonj
的WorkManager
作为其后台实现。 -
ConcurrentTaskExecutor
:该实现是java.util.concurrent.Executor
对象的适配器,一般不会使用。如果觉得ThreadPoolTaskExecutor
不够灵活,可以使用。
TaskScheduler 接口
概览
简单分析
TaskScheduler
接口是定时器的抽象,包含一组方法,用于指定任务执行的时间。Spring 主要提供两个实现TimerManagerTaskScheduler
和 ThreadPoolTaskScheduler
。
-
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);
}
-
ThreadPoolTaskScheduler
是最常用的,spring自定义的标签<task:scheduler>
使用的就是这个类。
Trigger 接口
概览
简单分析
- 在
TaskScheduler
接口中,可以使用Trigger
接口实现任务的执行。而Trigger
是抽象了出发任务执行的触发器。Spring内置了CronTrigger
和PeriodicTrigger
。 -
PeriodicTrigger
是直接按照给定的时间间隔触发任务执行 -
CronTrigger
是使用Cron 表达式指定什么时候执行任务
实现
Spring Scheduler 使用非常简单,只依赖Spring,不需要其他依赖。
Xml配置实现
- 定义任务:最简单的一个java类,不需要任务其他
public class Task {
public void doTask() {
System.out.println("~~~ doTask 定时任务被执行 ~~~");
}
public void doTaskFixedDelay() {
System.out.println("~~~ doTaskFixedDelay 定时任务被执行 ~~~");
}
}
- 任务配置
# 定义任务的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>
-
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"/>
-
TaskScheduler
配置
-
<task:scheduler>
注册一个ThreadPoolTaskScheduler
定时器 -
pool-size
属性设置线程池大小,默认是 1
<task:scheduler id="scheduler" pool-size="10"/>
注解实现
- 定义任务,并且配置任务
-
@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 定时任务被执行 ~~~");
}
}
- 配置注解支持
-
<task:annotation-driven>
配置注解@Scheduled
和@Async
的支持。其实在JavaConfig中EnableScheduling
、EnableAsync
代替。 -
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"/>
- 配置
TaskExecutor
、TaskScheduler
<task:scheduler id="scheduler" pool-size="10"/>
<task:executor id="executor" pool-size="10" queue-capacity="10" rejection-policy="ABORT"/>
集成 SpringBoot (Java Config 实现)
- 定义任务
@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 定时任务被执行 ~~~");
}
}
- 任务的配置,使用
JavaConfig
代替XMl
中配置,原则上来说,如果不需要自定义,只需要配置@EnableScheduling
即可实现功能。
-
@EnableScheduling
代替<task:annotation-driven>
中用于@Scheduled
的功能。@Async
的使用需要使用@EnableAsync
注解 -
SchedulingConfigurer
全局自定义配置需要实现该接口,重写configureTasks()
方法。如果@Async
的配置需要实现AsyncConfigurer
-
ScheduledTaskRegistrar
任务注册。支持添加TaskExecutor
、TaskScheduler
、执行任务等。
@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);
}
}
参考