Schedule/Quartz
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持久化的话)