导图社区 定时任务Quartz
定时任务详解思维导图,含四个方面:理论基础、Timer、线程池和quartz。
这是一篇关于运营中台功能-现状的思维导图,介绍了数字员工管理、 运营策略管理、 数据分析、 系统管理等。
linux自带的定时任务:优点:方便修改定时规则,支持一些较复杂的定时规则,通过文件可以统一管理配好的各种定时脚本。
社区模板帮助中心,点此进入>>
论语孔子简单思维导图
《傅雷家书》思维导图
《童年》读书笔记
《茶馆》思维导图
《朝花夕拾》篇目思维导图
《昆虫记》思维导图
《安徒生童话》思维导图
《鲁滨逊漂流记》读书笔记
《这样读书就够了》读书笔记
妈妈必读:一张0-1岁孩子认知发展的精确时间表
定时任务
理论基础
小顶堆
时间轮算法
链表或者数组实现时间轮(while-true-sleep)
遍历数组,每个下标放置一个链表,链表节点放置任务,遍历到了就取出执行
round时间轮
任务上记录一个round,遍历到了就将round减一,为0时取出执行
需要遍历所有的任务,效率较低
分层时间轮
使用多个不同时间维度的轮
天轮:记录几点执行
月轮:记录几号执行
月轮遍历到了,将任务取出放到天轮里面,即可实现几号几点执行
Timer
TaskQueue: 小顶堆,存放timeTask
TimerThread:任务执行线程
死循环不断检查是否有任务需要执行了,有就执行它
还是在这个线程执行
单线程执行任务,任务有可能相互阻塞
schedule:任务执行超时,会导致后面的任务往后推移,预想在这个时间内存档的任务执行就没了
scheduleAtFixedRate:任务超时可能导致下一个任务就会马上执行
运行时异常会导致timer线程终止
任务调度时基于绝对时间的,对系统时间敏感
线程池
ScheduledThreadPoolExecutor
使用多线程执行服务,不会相互阻塞
如果线程失活,会新建线程执行任务
线程抛异常,任务会被丢弃,需要做捕获处理
DedayedWorkQueue:小顶堆、无界队列
在定时任务线程池中,最大线程数时没有意义的
执行时间距离当前时间越近的任务在队列的前面
用于添加ScheduleFutureTask(继承于FutureTask,实现RunnableScheduledFunction)
线程池中的线程从DelayQueue中获取ScheduleFutureTask,然后执行任务
实现了Delayed接口,可以通过getDelay方法来获取延迟时间
Leader-Follower模式
避免没必要的唤醒和阻塞的操作,这样会更加有效,且节省资源
应用场景
使用于多个后台执行周期性任务,同时为满足资源管理的需求需要限制后台线程数量
SingleThreadScheduledExecutor
单线程的ScheduledThreadPoolExecutor
适用于需要单个后台线程执行周期任务,同时需要保证任务顺序进行
quartz
job:封装成jobDetail设置属性
@DisallowConcurrentException:禁止并发的执行同一个job定义(JobDetail定义的)多个实例
@PersistJobDataAfterException:持久化JobDetail中的JobDataMap(对trigger中的datamap无效)
如果一个任务请求恢复,一般是该任务执行期间发生了系统崩溃或其他关闭进程的操作,当服务再次启动时,会再次执行此任务。此时,jobExecutionContext.isRecovering()会返回true
Trigger:触发器,指定执行时间、开始结束时间等
优先级
同时触发trigger之间才会比较优先级
如果trigger是可恢复的,在恢复后再次调度时,优先级不变
misfire:错过触发
判断misfire的条件
job到达触发时间没有被执行
被执行的延迟时间超过了Quartz配置的misfireThreshold阈值
产生的原因
当job到达触发时间时,所有的线程都被其他job占用,没有可用线程
在job需要触发的时间点,scheduler停止了(可能时意外停止的)
job使用了@DisallowConcurrentExecution注解,job不能并发执行,当达到下一个job执行时间点的时候,上一个任务还没有完成
job指定了过去的开始执行时间,例如当前时间是8点整,指定开始时间为7点整
策略
默认使用MISFIRE_INSTRUCTION_SMART_POLICY策略
SimpleTrigger
now相关的策略,会立即执行第一个misfire的任务,同时会修改startTime和repeatCount,因此会重新计算finalFireTime,原计划执行时间会被打乱
next*相关的策略,不会立即执行misfire的任务,也不会修改startTime和repeatCount,因此finalFireTime也没有改变,发生了misfire也还是按照原计划进行执行
CronTrigger
MISFIRE_INSTRUCTION _IGNORE_MISFIRE_POLICY
Quartz不会判断发生了misfire,立即执行所有发生了misfire的任务,然后按照原计划进行执行 例如:在10:15立即执行9:00和10:00任务,然后等待下一个任务在11:00执行,之后按照原计划执行
MISFIRE_INSTRUCTION _FIRE_ONCE_NOW
立即执行第一个发生misfire的任务,忽略其他发生misfire的任务,然后按照原计划继续执行。 例如:在10:15立即执行9:00的任务,忽略10:00任务,然后等待下一个任务在11:00执行,之后按照原计划执行
MISFIRE_INSTRUCTION_DO_NOTHING
所有发生misfire的任务都被忽略,知识按照原计划继续执行
calendar:用于排除时间段
SimpleTrigger: 具体时间点,指定间隔重复执行
CronTrigger: cron表达式
Scheduler:调度器,基于trigger的设定执行job
SchedulerFactory
创建Scheduler
DirecSchedulerFactory:在代码里定制Scheduler参数
StdSchedulerFactory:读取classpath下的quartz.properties配置来实例化Scheduler
JobStore
存储运行时信息的,包括Trigger、Scheduler、业务锁等
RAMJobStore(内存实现)
JobStoreTX(JDBC,事务由Quartz管理)
JobStoreCMT(JDBC,使用容器事务)
ClusteredJobStore(集群实现)
TerracottaJobStore(Terracotta中间件)
ThreadPool
SimpleThreadPool
自定义连接池
JobDataMap:保存任务实例的状态信息
jobDetail
默认只在Job被添加到调度程序(任务执行计划表)scheduler的时候,存储一次该任务的状态信息数据,可以使用注解@PersistjobDataAfterException注解标明在一个任务执行完毕后就存储一次
trigger
任务被多个触发器引用的使用的时候,根据不同的触发时机,可以提供不同的输入条件