Quartz学习
创始人
2024-02-06 23:47:47
0

任务执行流程

  1. StdSchedulerFactory创建和属性初始化
    如果自定义了属性,会在这里加载
    在这里插入图片描述
  2. StdScheduler创建
    入口为StdSchedulerFactory#getScheduler();,首次进入时调用StdSchedulerFactory#instantiate
    1. 如果没有配置自定义属性,则先读取默认的quartz.properties文件配置
    2. 创建ClassLoadHelper并初始化
      在这里插入图片描述
    3. 创建JobFactory,默认实现为SimpleJobFactory,用来产生用户自定义的Job接口实现类的实例
    4. 创建ThreadPool,默认实现为org.quartz.simpl.SimpleThreadPool,并将org.quartz.threadPool开头的配置通过反射的方式赋予实例,这就是用来执行定时任务的线程池。
      org.quartz.threadPool.threadCount: 10org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
    5. 初始化JobStore,默认为RAMJobStore,并将org.quartz.jobStore相关配置赋值(如org.quartz.jobStore.misfireThreshold: 60000控制misfire阈值)
    6. 如果有数据源持久化配置,读取前缀为org.quartz.dataSource的进行配置
    7. 如果有SchedulerPlugin插件配置,读取前缀为org.quartz.plugin的进行配置
    8. 如果有JobListener配置,读取前缀为org.quartz.jobListener的进行配置
    9. 如果有TriggerListener配置,读取前缀为org.quartz.triggerListener的进行配置
    10. 创建ThreadExecutor,未配置时默认创建DefaultThreadExecutor ,execute(thread)时直接执行thread#start`
    11. 创建JobRunShellFactory,被用来构建JobRunShell实例
      未开启org.quartz.scheduler.wrapJobExecutionInUserTransaction时,默认创建JTAAnnotationAwareJobRunShellFactory
    12. 创建QuartzSchedulerResources,包装上述组件和一些配置信息
    13. 为ThreadPool#setInstanceName 为配置项org.quartz.scheduler.instanceName: DefaultQuartzScheduler,setInstanceId为org.quartz.scheduler.instanceId:NON_CLUSTERED
    14. SimpleThreadPool#initialize
      1. 创建org.quartz.threadPool.threadCount: 10个实现自Thread的WorkerThread,线程前缀为如DefaultQuartzScheduler_Worker-,则工作线程名为如DefaultQuartzScheduler_Worker-1。最后都放入列表workers
      2. 启动workers中所有WorkerThread,并加入SimpleThreadPool.availWorkers等待派发任务
      3. WorkerThread#run方法会不断循环,尝试执行内部runnable,没有派发的runnable就lock.wait(500)休息500ms;如果有任务,就执行,完成后将本WorkerThread重新加入SimpleThreadPool.availWorkers
    15. 使用上述信息创建QuartzScheduler,可用来注册调度job、JobListener等
      1. 创建并启动QuartzSchedulerThread,初始paused=true,halted=false
      2. QuartzSchedulerThread#run方法,halted==false时,会不断做以下工作:
        1. RAMJobStore#acquireNextTriggers,获取不超过当前时间30秒的、Math.min(availThreadCount, qsRsrcs.getMaxBatchSize())个OperableTrigger。
          具体来说,是从TreeSet timeTriggers中获取。依次比较nextFireTime越早越优先(trigger在首次scheduler#schedule时会调用computeFirstFireTime存储,以后每次触发就更新)、优先级越大越优先、key字典序排序优先。
        2. 对取出的Trigger计算Misfire规则
          1. misfireTime = now - org.quartz.jobStore.misfireThreshold: 60000
          2. 如果下次nextFireTime==null 或 nextFireTime > misfireTime 或 配置了 MisfireHandlingInstructionIgnoreMisfires,则说明不会misfire
          3. 否则说明会misfire,先通知triggerListeners该trigger发生misfire,然后根据MISFIRE_INSTRUCTION策略按需更新trigger.newFireTime
          4. 最后,如果nextFireTime为null,则说明已经STATE_COMPLETE,通知SchedulerListener,并从timeTriggers移除;否则继续判断newFireTime是否已经被更新,若未更新则表示没有misfire(ignore),否则表示已经更新且当次触发misfire。
        3. 如果trigger触发了mifire且nextFireTime不为null,则更新到timeTriggers
        4. 如果trigger.nextFireTime 超过当前时间30秒的,则加入timeTriggers
        5. 如果Job含有@DisallowConcurrentExecution注解,说明不能并行运行,则该jobKey除了第一个以外的Trigger都放入timeTriggers等待下次触发
        6. 更新可触发的trigger.state=TriggerWrapper.STATE_ACQUIRED
        7. 因为默认的maxBatchSize为1,所以这里就只取这个trigger
      3. 等到trigger.nextFireTime距离now 2ms以内时,就goAhead:RAMJobStore#triggersFired:
        1. 获取prevFireTime
        2. 更新nextFireTime
        3. tw.state = TriggerWrapper.STATE_WAITING;
        4. 将上述信息组装为运行时信息类TriggerFiredBundle
        5. Job含有@DisallowConcurrentExecution注解,则同jobKey的其他trigger变为TriggerWrapper.STATE_BLOCKED,并从timeTriggers移除,放入blockedJobs;否则放入timeTriggers等待下次触发
        6. JobRunShellFactory使用TriggerFiredBundle创建JobRunShell,传入StdCheduler、TriggerFiredBundle,并调用其initialize方法,创建用户自定义Job的实例
        7. threadPool#runInThread(JobRunShell),使用一个可用WorkerThread来运行JobRunShell

更多好文

  • 阅读源码——Quartz源码分析之任务存储
  • 阅读源码——Quartz源码分析之任务调度

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...