Quartz是一个任务调度框架,其框架中定义了如下三个基本组件,
- Job 执行任务
- Trigger 触发器,任务触发条件(周期性、定时等)
- Scheduler 调度器,接受触发器和执行任务对象,实现任务的定时、远程、分布式调度
Quartz作为一个优秀的任务调度框架,其支持从简单的单一应用定时任务,到复杂的远程任务和集群(分布式)任务调度,支持任务调度功能的高可用、高性能、高可扩展性部署。
本文将给出Quartz的代码使用样例,演示了从简单到复杂应用场景的使用方法,供快速应用时参考,
- 简单的定时任务
- Cron定时任务
- 远程任务调度
- 集群(分布式)任务调度
1. 简单的定时任务
一个简单的定时任务样例代码见这里,其分三个主要步骤,
- 创建job/trigger/scheduler三个对象
- 初始化任务调度器,通过scheduler.scheduleJob(job, trigger)绑定触发器和执行任务
- 启动调度器scheduler,通过scheduler.start()实现任务的定时触发。
详细演示步骤见下文的完整代码样例。
下面是简略代码,
JobDetail job = JobBuilder.newJob(HelloJob.class)
.withIdentity("MyJob", "MyGroup")
.build();
// a trigger at an interval of 10 seconds with 10 repeated times
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("MyTrigger", "MyGroup")
.startAt(new Date())
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10))
.build();
// scheduler job and start
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.scheduleJob(job, trigger);
scheduler.start();
//sleeping for scheduler to run job
Thread.sleep(60 * 1000L);
// shutdown the scheduler gracefully
scheduler.shutdown(true);
这里需要说明的是,
1) Job/Trigger的唯一标识
Job/Trigger有组group和名字name的联合唯一标识,在一个触发器中不允许有两个相同标识的Job/Trigger存在。若有的话,会抛出如下异常信息,
Exception in thread "main" org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'MyGroup.MyJob', because one already exists with this identification.
2) Scheduler任务线程池
一旦执行scheduler.scheduleJob(job, trigger)之后,则会默认启动10个任务工作线程,整个scheduler的状态为,
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
这个时候调度器还未正式启动任务调度,需要执行scheduler.start()后才真正开始运行。
通过jvisualvm.exe工具可以查看scheduler.scheduleJob()之后的线程情况,
注意的是,若任务结束后,程序没有调用scheduler.shutdown()的话,则整个程序还会一直在运行中。
2. Cron定时任务
一个cron定时任务样例代码见这里,其步骤和上述代码样例差不多,不一样之处在于触发器的定义从SimpleTrigger变成了CronTrigger,
// a cron scheduler at every 10 seconds
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("MyTrigger", "MyGroup")
.startAt(DateBuilder.evenMinuteDate(new Date()))
.endAt(new Date(System.currentTimeMillis() + 60 * 1000))
.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?"))
.build();
详细演示步骤见下文的完整代码样例。
Cron表达式非常灵活,其可以覆盖广泛的定时任务定义,下面是一些常见的任务定时表达式样例,
Cron表达式 | 含义 |
---|---|
0/20 * * * * ? | 每隔20秒 |
15 0/2 * * * ? | 每隔2分钟的第15秒,例如00:02:15,00:04:15,依次类推 |
0 0/2 8-17 * * ? | 每天08-17点,每隔2分钟 |
0 0 10am 1,15 * ? | 每月的第1天和第15天,上午10:00触发 |
0,30 * * ? * MON-FRI | 周一到周五,每到0,30秒时触发,比如周一的00:00:00,00:00:30,依次类推。 更多周天代码,周一MON,周二 TUE,周三 WED,周四 THU,周五 FRI,周六SAT,周日 SUN |
0,30 * * ? * SAT,SUN | 周六和周日,每到0,30秒时触发 |
3. 远程任务调度
在很多情况,任务的调度和执行并不在同一台机器,这个时候可以使用远程任务调度功能。一个远程任务调度的代码样例见这里。其主要包括两个步骤,
若从代码上分析,其和上述的单机版本任务调度并无区别,远程任务调度的不一样之处在于启动配置文件。下面为两个简略启动脚本,
java -Dorg.quartz.properties=server.properties -classpath "./demo-quartz.jar" com.pphh.demo.remote.RemoteSchedulerServer
java -Dorg.quartz.properties=client.properties -classpath "./demo-quartz.jar" com.pphh.demo.remote.RemoteSchedulerClient
可以看到,启动配置直接影响着调度器的行为,配置调度器实现远程调度功能,包括客户端和服务端。
1) 客户端配置
在配置文件client.properties中主要有如下三个配置项,
org.quartz.scheduler.rmi.proxy: true
org.quartz.scheduler.rmi.registryHost: localhost
org.quartz.scheduler.rmi.registryPort: 1099
上述配置项定义了客户端的远程服务代理。
2) 服务器配置
在配置文件client.properties中主要有如下四个配置项,
org.quartz.scheduler.rmi.export: true
org.quartz.scheduler.rmi.registryHost: localhost
org.quartz.scheduler.rmi.registryPort: 1099
org.quartz.scheduler.rmi.createRegistry: true
上述配置项定义了服务器端的远程服务接受。
详细的远程任务调度演示步骤见下文的完整代码样例。
4. 集群(分布式)任务调度
集群任务调度也叫做分布式任务调度,主要为了满足任务调度的高可用、高性能、高可扩展性的需求。
一个基于Mysql数据库的集群任务调度代码样例见这里。其主要包括三个步骤,
- 初始化数据库表字段,准备存储任务调度信息,mysql初始化脚本
- 创建任务调度,保存到数据库中,代码样例
- 启动多个集群实例,实现任务的集群调度,代码样例
Quartz的集群调度依赖数据库实现任务的调度一致性,支持的数据库非常广泛。不同数据库的初始化脚本可以下载官方的发布包,解压后在文件目录./docs/dbTables中获取。
详细的集群任务调度演示步骤见下文的完整代码样例。
5. 完整代码样例和演示
演示代码仓库地址:https://gitee.com/pphh/simple-demo,可以通过如下git clone命令获取仓库代码,
git clone git@gitee.com:pphh/simple-demo.git
完整演示项目代码位于文件目录./demo-quartz-scheduler中。
整个项目的演示步骤请见README文件,请参考说明文件对项目进行编译构建,并运行演示程序。
6. 参考文档
- Quartz-Scheduler官方代码仓库:https://github.com/quartz-scheduler/quartz
- Quartz-Scheduler官方发布包:http://www.quartz-scheduler.org/downloads/