由先前的文章,我们已经验证了Quartz到集群模式、触发器优先级、任务错过触发处理和任务有状态与并发等场景特性。
删除正运行任务
测试结果
任务删除将删除还未触发的任务及触发器信息。但不会强行中断已经触发运行的任务。
测试步骤
1、定义一个任务为休眠10秒。
2、测试用例中,任务每2秒触发。等待6秒后删除任务。
查看结果,加入任务后,数据库保存了任务信息。
由于任务每2秒触发,而6秒后删除任务,共触发了4次,即6秒后删除任务,没有新的触发任务。删除任务也不会强行中断正在触发的任务。
最后,数据库任务信息也删除了。
代码参见
调度器根据JobKey删除任务及其相关触发器,并通知调度线程
org.quartz.core.QuartzScheduler.deleteJob(JobKey)
集群下调度实例ID生成
测试结果
集群模式下,调度实例ID可配置自动生成,生成方式为:当前主机名 + 当前时间毫秒数
测试步骤
1、配置文件将调度实例ID设为AUTO,并加入集群
org.quartz.scheduler.instanceId: AUTO org.quartz.jobStore.isClustered=true
2、跟踪调度工厂org.quartz.impl.StdSchedulerFactory
加载配置启动过程
3、实例ID生成器org.quartz.spi.InstanceIdGenerator.generateInstanceId()
生成ID
可以看出默认生成器ID生成规则:HOSTNAME + CURRENT_TIME
打印日志可以看出实例ID
配置文件可以设置org.quartz.scheduler.instanceIdGenerator.class
属性,指向自定义的ID生成器,自行实现ID生成算法。
优雅关机
测试结果
手动关闭Quartz调度,即调用Shutdown方法时,会停止正在运行的触发器和清除所有调度相关的资源。关闭调度线程、关闭错过触发线程、关闭集群管理线程、关闭连接池、关闭线程池,设为True时,关闭时会等待到所有任务线程执行结束。
测试步骤
定义一个任务休眠20s,任务触发后等待15s,关闭调度。发现调度关闭会等待正在执行的任务直到任务线程结束。
发现触发器还是持久化到数据库。
代码参见
调度器关闭方法,关闭线程、关闭触发器、关闭连接池、关闭线程池等等
org.quartz.core.QuartzScheduler.shutdown(boolean)
设计模式
quartz内部也应用了一些设计模式,贴下代码吧
工厂模式
quartz采用了工厂方法。调度工厂SchedulerFactory的实现类有两个标准调度工厂StdSchedulerFactory和直接调度工厂DirectSchedulerFactory,StdSchedulerFactory可通过quartz配置文件初始化调度器Scheduler,而DirectSchedulerFactory可通过创建调度器方法来获取不同类型调度器。
任务运行壳工厂JobRunShellFactory,主要有两种实现类,创建有JTA事务和没有事务的JobRunShell。JTAJobRunShellFactory会负责创建含有JTA事务的JTAJobRunShell线程,用来反射执行真正的Job任务,并包裹了一层JTA事务;而StdJobRunShellFactory负责创建简单的JobRunShell,不处理事务相关的东西
建造者模式
Quartz提供了不同触发器类型的触发器建造者,建造者支持属性设值的链式写法
触发器建造者,可以创建不同触发器类型的触发器
org.quartz.JobBuilder
任务建造者,负责创建JobDetail实例
org.quartz.DateBuilder
日期建造者,负责创建与任务相关的具体日期
观察者模式
org.quartz.JobListener
任务监听器,任务执行会通知改监听器
org.quartz.TriggerListener
触发器执行会通知触发器监听器
org.quartz.SchedulerListener
调度器监听器,调度器启动和关闭等动态变化、触发器动态变化、任务动态变化会通知调度器监听器
org.quartz.ListenerManager
监听器管理类,对任务监听器、触发器监听器和调度器监听器管理
QuartzScheduler任务调度后,会负责通知监听器
单例模式
DirectSchedulerFactory.getInstance()
验证了删除正在运行任务,集群模式下调度实例ID生成和优雅关机等场景,和贴了quartz应用到的一些设计模式。quartz作为一款比较成熟的定时调度开源框架,受到广泛的应用和扩展不是没有道理的。
发表评论