设计订单的业务场景常常用到了定时任务来完成,而java中我常用到的定时任务框架就是Quartz。Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。但是相较于Timer, Quartz增加了很多功能:
- 持久性作业 - 就是保持调度定时的状态;
- 作业管理 - 对调度作业进行有效的管理;
Quartz由基本的三部分组成:
- JobDetail 任务 (做什么)
- Trigger 触发器 (什么时候做)
- Scheduler 调度器 (定时任务容器,装载任务和触发器)
Quartz Demo示例
在使用Quartz框架前需先通过maven引入依赖的jar包:
1 | <dependency> |
在导入依赖后创建一个任务,需实现 org.quartz.Job 接口并复写 execute 方法,在其方法中进行业务逻辑具体实现的编写。
1 | import org.quartz.Job; |
在写好一个任务后,还需要创建 Scheduler 来调度执行任务。
1 | public class DemoScheduler { |
这样一个简单的定时任务就创建好了。
关键类和接口
Job & JobDetail
Job 为作业的接口,为任务调度的对象;JobDetail绑定指定的Job,每次Scheduler调度执行一个Job的时候,首先会拿到对应的Job,然后创建该Job实例,再去执行Job中的execute()的内容,任务执行结束后,关联的Job对象实例会被释放,且会被JVM GC清除。为什么设计成 Job + JobDetail,而不直接使用Job?
JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。
任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,Sheduler每次执行,都会根据JobDetail接收一个 Job 实现类(JobDetail,描述 Job 的实现类及其他相关的静态信息,如 Job 名字、描述、关联监听器等信息),以便运行时通过 newInstance() 的反射机制实例化 Job。创建一个新的Job实例,这样就可以规避并发访问的问题。JobExecutionContext
JobExecutionContext中包含了Quartz运行时的环境以及Job本身的详细数据信息。
当Schedule调度执行一个Job的时候,就会将JobExecutionContext传递给该Job的execute()中,Job就可以通过JobExecutionContext对象获取信息。Trigger
Trigger:是一个类,描述触发 Job 执行的时间触发规则,一个 Trigger 只能对应一个作业实例,而一个作业实例可对应多个触发器;主要有 SimpleTrigger 和 CronTrigger 这两个子类。当且仅当需调度一次或者以固定时间间隔周期执行调度,SimpleTrigger 是最适合的选择;而 CronTrigger 则可以通过 Cron 表达式定义出各种复杂时间规则的调度方案。个人在日常开发中CronTrigger用的更多。Scheduler
Scheduler 做为定时任务容器,是 Quartz 最上层的东西,它提携了所有触发器和作业,使它们协调工作,每个 Scheduler 都存有 JobDetail 和 Trigger 的注册,一个 Scheduler 中可以注册多个 JobDetail 和多个 Trigger。