Schedule/Quartz

优质
小牛编辑
130浏览
2023-12-01

Ovewview

对于固定时间间隔的任务,JDK自带的Executor已足够好。

简单的Cron式定时任务,Spring自带的Scheduler也能执行,不再一定需要quartz了。

Spring的Scheduler模块还有schedule-task的namespace,可以不需更改任何代码,快速配置Timer/Cron式任务的执行,唯一缺陷是在JVM退出时只有简单的shutdown()或shutdownNow(),没有超时控制。另外任务调用时用的是反射。

至于Spring的annotation式配置任务,感觉是严重的白费力了,配置总是要摆在xml里的。

Quartz更大的优势体现在保证集群中有且仅有一台服务器执行了任务,而且用JDBC持久化任务,保证任务不会被漏掉。

SpringSide里还基于Redis实现了一种定时任务,有海量的一次性定时任务,每个任务在集群里只被执行一次,需要整个集群参与处理任务。此时Quartz的JDBC的性能无法支撑。

Showcase中的演示

Showcase中演示了所有的技术选型:

1. JDK Timer

JdkTimerJob既是任务配置者,也同时是Runnable执行者。
在@PostConstruct中配置并启动任务,使用了Guava的ThreadFactoryBuilder配置任务线程的命名,使用了Spring的 TaskUtils.decorateTaskWithErrorHandler(this)方法,保证任务在异常时不会被打断。
在@PreDestroy时关闭任务线程。使用了自己封装的Threads.normalShutdown()控制超时。

以上三点都是直接用JDK Timer时需要注意的地方!!!

2. Spring Cron

SpringCronJob既是任务配置者,也同时是Runnable执行者。
在@PostConstruct中使用了Spring的ThreadPoolTaskScheduler和CronTrigger,配置cron任务并指定线程命名。 在@PreDestroy时同样使用自己封装的Threads.normalShutdown()关闭线程且控制超时。

3. Spring Task Scheduler XML

applicationContext-spring-scheduler.xml, 无需任何java代码,直接配置任务,用反射来调用执行。与前两种相比,只是少了系统shutdown时的超时控制。

4. Quartz任务

Quartz任务有Timer和Cron,有单独执行和集群执行,有反射调用与继承于QuartzJobBean几种不同,分别在QuartzClusterableJob, applicationContext-quartz-cron-local.xml和applicationContext-quartz-timer-cluster.xml 中做了演示。

其中最特别是Cluster模式下,任务类本身也要持久化到数据库里,要求任务类及其属性都是可持久化的,像XXService这种属性就不能有了,需要用applicationContext,在需要的时候再动态取出。

升级Quart2.1与Spring3.1+

Quartz2.1的API让大家不再依赖Spring的封装也能在applicationContext-*.xml中配置任务了。如果要继续用,那些JobDetailBean,MethodInvokingJobDetailBean,SimpleTriggerBean和CronTriggerBean 统统在"Bean"前面加上"Factory",比如CronTriggerFactoryBean.

最后升级一下数据库(如果有集群的,用jdbc持久化的话)