由于某种原因,例如应用停掉,导致定时任务错过了本该执行的时间点,这就是定时任务过期。对于过期的定时任务,我们需要基于某种策略对其进行处理。

过期策略

在Trigger接口中定义了两种过期策略,

    public static final int MISFIRE_INSTRUCTION_SMART_POLICY = 0;public static final int MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1;

MISFIRE_INSTRUCTION_SMART_POLICY 表明过期的定时任务将使用智能策略,如何处理将依赖于具体的Trigger实现类。等会我们会专门分析最常用的CronTrigger的智能过期策略的实现。
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY 表明对于过期的定时任务将不执行任何过期策略。

设定过期策略

以CronTrigger为例,我们在添加定时任务的时候可以通过CronSchedulerBuilder设定过期策略。

 JobDetail jobDetail = JobBuilder.newJob(PrintJob.class).storeDurably(true).withIdentity(id).withDescription(desc).setJobData(jobDataMap).build();CronScheduleBuilder schBuilder = CronScheduleBuilder.cronSchedule(cron)
.withMisfireHandlingInstructionFireAndProceed();Trigger trigger = TriggerBuilder.newTrigger().withIdentity(id).withDescription(desc).forJob(jobDetail).withSchedule(schBuilder).build();

如果不指定默认就是MISFIRE_INSTRUCTION_SMART_POLICY ,即采用智能策略模式。

CronTrigger过期策略

CronTrigger的智能过期策略有两种

public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1;
public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2;

看字面意思很好理解,第一种是立即触发一次,第二种是忽略掉不管。定时任务过期后,需要对triiger进行处理,具体的处理是在具体的Trigger实现类中实现的,例如CronTriggerImpl

@Overridepublic void updateAfterMisfire(org.quartz.Calendar cal) {int instr = getMisfireInstruction();if(instr == Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY)return;if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) {instr = MISFIRE_INSTRUCTION_FIRE_ONCE_NOW;}if (instr == MISFIRE_INSTRUCTION_DO_NOTHING) {Date newFireTime = getFireTimeAfter(new Date());while (newFireTime != null && cal != null&& !cal.isTimeIncluded(newFireTime.getTime())) {newFireTime = getFireTimeAfter(newFireTime);}setNextFireTime(newFireTime);} else if (instr == MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) {setNextFireTime(new Date());}}

从源码中可以看到,CronTrigger的默认智能策略就是立即触发一次(MISFIRE_INSTRUCTION_FIRE_ONCE_NOW),即更新下次触发时间为当前时间。

过期定时任务检测

前半部分我们讲了定时任务的过期策略,并以CronTrigger为例,说明了其智能过期策略是如何实现的。后半部分,我们将视角从Trigger提升到Scheduler,看看Quartz是如何检测出过期定时任务的。

在JobStoreSupport中有一个叫MisfireHandler的线程,它负责定期检测出那些过期的定时任务。我们来看看它是如何做的。

首先,我们要明确一个过期的标准。一个比较直观的想法就是,如果一个Trigger的下次触发时间在当前时间之前,那么这个定时任务肯定是过期了。但是我们为了给人家一个机会,可以通过减去一个值,稍稍把这个截止时间调前一点。这个值可以通过quartz.properties配置,默认是60000,即60秒。

org.quartz.jobStore.misfireThreshold: 10000

当然Trigger必须是WAITING状态下才行,非WAITING状态的Trigger表明定时任务正在处理,已经完成或者出错了。而且过期策略不是MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY 。

有了这三个过期指标,过期的定时任务就好筛选了。我们去QRTZ_TRIGGERS表里面,把符合这三个条件的Trigger都筛选出来。

过期定时任务恢复

以MISFIRE_INSTRUCTION_FIRE_ONCE_NOW过期策略为例,拿到过期的Trigger后,根据过期策略,调用updateAfterMisfire()对其进行更新,包括设置下次触发时间,更新状态为WAITING。

处理完trigger后,MisfireHandler会立即向QuartzSchedulerThread发送信号,告诉有紧急任务达到。

if (recoverMisfiredJobsResult.getProcessedMisfiredTriggerCount() > 0) {signalSchedulingChangeImmediately(recoverMisfiredJobsResult.getEarliestNewTime());
}

QuartzSchedulerThread接收到信号后,如果才刚刚开始扫描触发器则必定能扫描到这个触发器,所以不用做任何额外处理。如果已经获取过触发器了,则释放掉已经获取的触发器,重新开始扫描。

if(releaseIfScheduleChangedSignificantly(triggers, triggerTime)) {break;
}

Quartz定时任务过期处理策略相关推荐

  1. 详细总结:分布式, Nginx Linux Redis 微服务 Dubbo框架 Quartz定时任务

    目录 1.1 概念 2.1分布式概念 2.2分布式项目拆分 2.3分布式项目总结 2.3 分布式事务 3.1 Nginx配置文件介绍 3.2 实现负载均衡(Tomcat高可用) 3.3 常见面试题 4 ...

  2. 大数据互联网架构阶段 QuartZ定时任务+RabbitMQ消息队列

    QuartZ定时任务+RabbitMQ消息队列 一 .QuartZ定时任务解决订单系统遗留问题 情景分析: 在电商项目中 , 订单生成后 , 数据库商品数量-1 , 但是用户迟迟不进行支付操作 , 这 ...

  3. Quartz定时任务的基本搭建

    前言 个人地址:Quartz定时任务的基本搭建 Quartz是一个完全由Java编写的开源作业调度框架,为在java应用程序中进行作业调度提供了简单又强大的机制. Quartz中分为几个核心概念: J ...

  4. Redis的内存回收机制和数据过期淘汰策略

    本文来说下Redis的内存回收机制和数据过期淘汰策略 文章目录 概述 为什么需要内存回收 过期删除策略 定时删除 惰性删除 定期删除 删除策略比对 过期删除策略原理 redisDb结构体定义 expi ...

  5. Redis——过期时间/过期回收策略

    既然是缓存,就会涉及过期时间以及过期后清理回收内存的过程:本篇主要讲一下redis的key过期时间相关的命令.注意事项.回收策略: 注意:实际上,redis的内存回收触发有两种情况,上面说的是一种,也 ...

  6. Spring Boot配置Quartz定时任务

    1 Quartz定时任务 Quartz 是一个完全由 Java 编写的开源任务调度框架,为在 Java 应用程序中进行任务调度提供了简单却强大的机制. 基于定时.定期的策略来执行任务是它的核心功能,比 ...

  7. quartz定时任务开发cron常用网站

    http://cron.qqe2.com/   cron表达式   只能看下5个时点 http://www.cronmaker.com/     能看500个时点 https://unixtime.5 ...

  8. redistemplate.opsforhash设置过期时间_Redis详解(十一)------ 过期删除策略和内存淘汰策略...

    大家好,我是可乐,一个专注原创,乐于分享的程序猿. 本系列教程持续更新,可以微信搜索「 IT可乐 」第一时间阅读.回复<电子书>有我为大家特别筛选的海量免费书籍资料 在介绍这篇文章之前,我 ...

  9. Redis SLAVE过期键策略

    Redis SLAVE过期键策略 github博客地址 官方文档:redis.io/topics/repl- 原文截取: How Redis replication deals with expire ...

最新文章

  1. hdu 3805 Triangle Conjecture
  2. java 一些常用的代码(转载)
  3. 泛函编程—模板函数_类模板
  4. Javascript模块化编程
  5. 视频私有云实战:基于Docker构建点播私有云平台
  6. 嵩天-Python语言程序设计程序题--第一周:Python基本语法元素
  7. redis——NOSQL及redis概述
  8. Retrofit与RXJava整合
  9. OpenCV人脸识别之三:识别自己的脸
  10. HTML5 -- WebSocket
  11. 常见面试算法:回归、岭回归、局部加权回归
  12. 轻量级linux iso,antiX 17.2 发布,基于Debian的轻量级Linux发行版
  13. 如何让Toast响应点击事件等基础Android基础文章N篇
  14. 不要小看它——编码与解码
  15. Git/Repo/Gerrit区别
  16. php中绘制长方体,php代码将常见的长方形图片修改为正方形的图片
  17. 译:Self-Modifying cod 和cacheflush
  18. [system] Map key not configured.
  19. web前端入门到实战:纯CSS实现数据上报和HTML验证
  20. a标签的href属性与事件修饰符阻止默认行为

热门文章

  1. Skynet天网监测到的数笔可疑交易背后:又一欺诈项目Forest Tiger Pro被确认
  2. 电动汽车 simulink仿真模型,可进行整车动力性仿真测试(最高车速,最大爬坡,加入时间)和NEDC工况能耗测试(电耗)
  3. vlc录制网络流_基于PortAudio+LAME3实现的ASIO多通道音频录制mp3
  4. 为什么打不开计算机音乐模式,电脑中酷狗音乐无法打开的解决方法
  5. 【ubuntu】安装robo 3t
  6. 三峡好人 ---让张易某,陈凯哥学习学习什么才是真正的电影
  7. Java使用Socket实现服务器与客户端通信
  8. 个人喜欢的网站http://www.w3school.com.cn
  9. 隐私计算头条周刊(12.11-12.17)
  10. Hexo博客Next主题bilibili视频Markdown插入文章