Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目。
学习Quartz之前我们需要了解几个概念:
我们可以把这里Job理解为一个进程下的多个线程,Job表示一个工作,也就是执行具体业务逻辑的一个类,它里面就一个方法execuate
void execute(JobExecutionContext context)
这里的JobDetail我么可以看作是一个封装的Job类,只有将具体的业务Job封装成JobDetail才可以被Quartz识别并调用。另外 JobDetail 还包含了这个任务调度的方案和策略。
代表一个调度参数的配置,即我们时候去调用在Trigger里设置
是一个整合JobDetail和Trigger的容器,一个Scheduler里可以放置多个JobDetail和Trigger
由上图我们可以清楚的了解到,一个jobDetail是由JobBuilder创建,一个Trigger是由TriggerBuilder创建。而JobDetail和Trigger里可以创建对应的JobDataMap,往Map里加一些参数,供execuate方法里获取到对应的JobDataMap根据键获取到对应的属性值。
【引入依赖】
<dependencies>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartzartifactId>
<version>2.3.2version>
dependency>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartz-jobsartifactId>
<version>2.3.2version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.12version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
dependencies>
【分析步骤】
// 创建一个scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
可以通过scheduler获取到
context
(这里的context就是execuate里面的参数JobExecutionContext context
),从而往里面设置一些属性
// 创建JobDetail 由JobBuilder创建
JobDetail job = JobBuilder.newJob(MyJob.class)
.withIdentity("myjob", "mygroup")
.usingJobData("j1", "jv1")
.build();
job.getJobDataMap().put("j2", "jv2");
// 创建Trigger 由TriggerBuilder创建
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.usingJobData("t1", "tv1")
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3)
.repeatForever()).build();
trigger.getJobDataMap().put("t2", "tv2");
由scheduler创建的JobDetail和Trigger都支持链式编程,
而且创建出来的JobDetail和Trigger都必须要添加一个属性withIdentity(String key,String value)
scheduler.scheduleJob(JobDetail,Trigger);
scheduler.start();
如上图所示,Trigger每隔2s调用一次JobDetail执行Job所实现的Job真正的业务
上述示例是一个SimpleScheduler调度的。
Scheduler:与调度程序交互的接口
Job:你想要调度器执行的任务的组件所实现的接口
JobDetail:用于定义任务作业的示例
Trigger:触发器,用于定时调用JobDetail所封装的Job的组件
JobBuilder:构建JobDetail的示例的
TriggerBuilder:用于构建Trigger的示例的
(1)使用Map获取
通过@PersistJobDataAfterExecuation注解使用
有状态的Job可以理解为多次Job调用期间可以持有一些信息,这些状态信息存储在JobDetail里面,而默认的无状态的Job每次调用都会创建一个新的JobDataMap。
和Job一样,Trigger也和Trigger一样很好使用,但是Trigger有很多的类型,这里只详细学习一下SimpleTrigger
和CornTrigger
两个核心的Trigger类型
注意:不管什么类型的Trgger,都有一个必须的属性:TriggerKey,用于唯一标识一个Trigger
除了TriggerKey以外,trigger还有一些公共属性。
SimpleTrigger可以满足的调度需求是:在具体的时间点执行一次,或者在具体的时间点执行,并且以指定的间隔重复执行若干次。比如,你有一个trigger,你可以设置它在2015年1月13日的上午11:23:54准时触发,或者在这个时间点触发,并且每隔2秒触发一次,一共重复5次。
SimpleTrigger的属性包括:开始时间、结束时间、重复次数以及重复的间隔。
可以是0、正整数,以及常量SimpleTrigger.REPEAT_INDEFINITELY
必须是0,正整数
public class MainHelloTrigger {
public static void main(String[] args) throws Exception {
// 任务调度器 StdSchedulerFactory
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 设置任务的开始时间
Date startDate = new Date();
// 延迟3s执行
startDate.setTime(startDate.getTime()+3000);
// 设置任务的结束时间
Date endDate = new Date();
endDate.setTime(endDate.getTime()+10000);
// 调度任务实例
JobDetail jobDetail = JobBuilder.newJob(HelloJobTrigger.class) // 加载任务类的实例
.withIdentity("helloJob", "HelloJobGroup") // 参数一:任务的名称(唯一实例);参数二:任务组的名称
.build();
// 触发器Trigger
Trigger trigger = TriggerBuilder.newTrigger() // 创建一个触发器
.withIdentity("HelloTrigger", "HelloTiggerGroup") // 参数一:触发器的名称;参数二:触发器的群组名
// .startNow() // 马上启动触发器 只执行一次
// .startAt(startDate) // 设置任务的开始时间
.endAt(endDate) .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5)) // 创建一个每5s重复执行一次的简单调度器
.build();
// 获取触发器的名称以及组的名称 同理Job 如果不指定组名,按默认去执行 任务/触发器的名称必须要指明
// 让调度器Scheduler关联触发器和任务
scheduler.scheduleJob(jobDetail,trigger);
// 启动scheduler调度任务
scheduler.start();
}
}
CronTrigger通常比Simple Trigger更有用,如果您需要基于日历的概念而不是按照SimpleTrigger的精确指定间隔进行重新启动的作业启动计划。
使用CronTrigger,您可以指定号时间表,例如“每周五中午”或“每个工作日和上午9:30”,甚至“每周一至周五上午9:00至10点之间每5分钟”和1月份的星期五“。
即使如此,和SimpleTrigger一样,CronTrigger有一个startTime,它指定何时生效,以及一个(可选的)endTime,用于指定何时停止计划。
Quartz以模块方式架构,因此,要是他运行,几个组件必须很好二点聚合在一起,幸运的是,已经有了一些现存的助手可以完成这些工作。
所有的Schedular实例都是由SchedularFactory创建。
Quartz的三个核心概念,调度器,任务,触发器。三者之间的关系是:
大家都知道,一个作业,比较重要的三个参数就是Scheduler,jobDetail,Trigger;而Trigger对于JOB而言就是好比一个驱动器;没有触发器来定时驱动作业,作业就无法运行;对于JobDetail而言,一个Job可以对应多个Trigger
创建Scheduler的方式有两种:
方式一:
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
方式二:
SchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
默认路径:quartz.2.3.0中的org.quartz中的quartz.properties
组成部分:
org.quartz.scheduler.instanceName:属性用来区分特定的调度器实例,可以按照功能用途来给调度器起名。
org.quartz.scheduler.instanceId:属性和前者一样,允许任何字符串,但是这个值必须要在所有的调度器实例中是唯一的,尤其是在一个集群的环境中。作为唯一的key。
threadCount
处理Job的线程数目,至少为1,但是最多的话最好不要超过100,再多台机器上设置值超过100的话,会显得相当不适用。特别是在Job执行时间较长的情况下。
现成的优先级,优先级高的线程优先得到执行。最小的1;其次最大的是10。默认是5