根据先前的概念简介可知,一个Job可以有多个相同或不同的Trigger触发,甚至是同时触发。不同的Job也可能同时触发。这时就出现了触发时间相同的触发器触发先后顺序问题,这就是触发器优先级要考虑的问题。这里直接上结果
测试结果:
默认情况是触发时间先后顺序排列,触发时间比较前的先执行任务,但如果一个或多个任务同时在相同时间触发下,触发器设置优先级越高越先执行。如果优先级相同,则跟任务的存储方式有关,RAMJobStore时与TriggerKey排序有关,即按触发器名的字母序;如果是JdbcStore则跟数据库查询的默认排序有关了。Trigger优先级默认为5,数值越大优先级越高。
测试步骤:
1、定义了3个任务,都是在17:12:00秒触发,优先级大小分别为10、100、1
测试结果为:SimpleJob数值最大,优先级最大,最先执行。
调换下优先级大小,FirstJob为1,SimpleJob为5,HelloJob为10。定点触发,结果是优先级最大的HelloJob最先执行。
2、优先级相同时,都设为5时,多测试几遍,FirstJob总是先执行。
代码参见
查看Quartz调度线程可知,与触发器的存储方式有关。QuartzSchedulerThread定义了获取下一个触发器队列的方法。
org.quartz.core.QuartzSchedulerThread#org.quartz.spi.JobStore.acquireNextTriggers(long, int, long)
如果是RAMJobStore,用TreeSet存储待触发的线程。Trigger类里定义了触发器时间比较器
可以看出,优先级按触发时间、优先级和TriggerKey(String的字母序)排序的。
而JdbcStore可以看下Jdbc委托类,查看触发器查询语句
org.quartz.impl.jdbcjobstore.StdJDBCDelegate
挑出触发器查询语句:
select * from qrtz_triggers ORDER BY NEXT_FIRE_TIME ASC, PRIORITY DESC
发现是按触发时间升序,优先级降序排列,如果都相同,采用数据库自己默认的排序了,跟具体的DB有关了。MySQL中SELECT 默认排序是按照物理存储顺序显示。
Trigger可以定义一个优先级,默认为5。当多个trigger同时触发job时,线程池可能不够用,此时根据优先级来决定谁先触发。数值越大优先级越高。这个可以考虑为配置项,为优先执行的Trigger设置较大的优先级数值。
所以所有获取待触发触发器列表,跟触发时间有关,其次是触发器优先级大小,最后是具体任务的存储方式有关。触发时间较前先触发,触发时间相同,触发器优先级大的先触发,如果触发器优先级相同,则看任务存储方式,若为内存存储,则与TriggerKey排序有关,即按触发器名的字母序,若为DB存储,则与DB默认排序规则有关。