quartz学习

来源:互联网 发布:赢时胜软件笔试题 编辑:程序博客网 时间:2024/05/19 00:13

Quartz API核心接口有:

  • Scheduler – 与scheduler交互的主要API;
  • Job – 你通过scheduler执行任务,你的任务类需要实现的接口;
  • JobDetail – 定义Job的实例;
  • Trigger – 触发Job的执行;
  • JobBuilder – 定义和创建JobDetail实例的接口;
  • TriggerBuilder – 定义和创建Trigger实例的接口;
Job方法实例:
QuartzTest类:
package quartzTest;import org.quartz.JobBuilder;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.SimpleScheduleBuilder;import org.quartz.Trigger;import org.quartz.TriggerBuilder;import org.quartz.impl.StdSchedulerFactory;public class QuartzTest {public static void main(String[] args) {new QuartzTest().run();}private void run() {try {//1.创建一个JobDetail实例,指定QuartzJobDetail jobDetail = JobBuilder.newJob(JobTest.class) //任务执行类.withIdentity("job1_1", "jGroup1") //任务名,任务组.build();//2.创建TriggerSimpleScheduleBuilder builder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10)     //设置间隔执行时间.repeatForever();             //设置执行次数Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1_1", "tGroup1").startNow().withSchedule(builder).build();//3.创建ScheduleScheduler scheduler = StdSchedulerFactory.getDefaultScheduler();//4.调度执行scheduler.scheduleJob(jobDetail,trigger);scheduler.start();} catch (SchedulerException e) {e.printStackTrace();}}}
JobTest类,实现Job接口:
package quartzTest;import org.quartz.Job;import org.quartz.JobDetail;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;public class JobTest implements Job{@Overridepublic void execute(JobExecutionContext jobContext) throws JobExecutionException {JobDetail jobDetail = jobContext.getJobDetail();String jobName = jobDetail.getClass().getSimpleName();System.out.println("JobName:" + jobName);System.out.println("JobClass:" + jobDetail.getJobClass());System.out.println(jobName + "开始于:" + jobContext.getFireTime());System.out.println("下一次开始时间:" + jobContext.getNextFireTime());}}

每次当scheduler执行job时,在调用其execute(…)方法之前会创建该类的一个新的实例;执行完毕,对该实例的引用就被丢弃了,实例会被垃圾回收;这种执行策略带来的一个后果是,job必须有一个无参的构造函数(当使用默认的JobFactory时);另一个后果是,在job类中,不应该定义有状态的数据属性,因为在job的多次执行中,这些属性的值不会保留。

        那么如何给job实例增加属性或配置呢?如何在job的多次执行中,跟踪job的状态呢?答案就是:JobDataMap,JobDetail对象的一部分。


JobDataMap

         JobDataMap中可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据;JobDataMap是java Map接口的一个实现,额外增加了一些便于存取基本类型的数据的方法。

将job加入到scheduler之前,在构建JobDetail时,可以将数据放入JobDataMap,如下示例:

package quartzTest;import org.quartz.Job;import org.quartz.JobDataMap;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.quartz.JobKey;public class JobTest implements Job{@Overridepublic void execute(JobExecutionContext jobContext) throws JobExecutionException {JobKey key = jobContext.getJobDetail().getKey();JobDataMap dataMap = jobContext.getJobDetail().getJobDataMap();//从JobDataMap中取数据String jobSays = dataMap.getString("jobSays");float myFloatValue = dataMap.getFloat("myFloatValue");System.out.println("Instance" + key + "of DumbJob says: " + jobSays + " and val is: " + myFloatValue);}}
给jobDataMap添加数据:

package quartzTest;import org.quartz.JobBuilder;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.SimpleScheduleBuilder;import org.quartz.Trigger;import org.quartz.TriggerBuilder;import org.quartz.impl.StdSchedulerFactory;public class QuartzTest {public static void main(String[] args) {new QuartzTest().run();}private void run() {try {//1.创建一个JobDetail实例,指定Quartz//JobDetail jobDetail = JobBuilder.newJob(JobTest.class) //任务执行类//.withIdentity("job1_1", "jGroup1") //任务名,任务组//.build();JobDetail jobDetail2 = JobBuilder.newJob(JobTest.class).withIdentity("job1_2", "jGroup")//                .usingJobData("jobSays","Hello World!")//                .usingJobData("myFloatValue", 3.141f)                .build();//给jobDataMap中添加数据jobDetail2.getJobDataMap().put("jobSays","Hello World!");jobDetail2.getJobDataMap().put("myFloatValue", 3.141f); //2.创建TriggerSimpleScheduleBuilder builder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10)     //设置间隔执行时间.repeatForever();             //设置执行次数Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1_1", "tGroup1").startNow().withSchedule(builder).build();//3.创建ScheduleScheduler scheduler = StdSchedulerFactory.getDefaultScheduler();//4.调度执行scheduler.scheduleJob(jobDetail2,trigger);scheduler.start();} catch (SchedulerException e) {e.printStackTrace();}}}
结果:

InstancejGroup.job1_2of DumbJob says: Hello World! and val is: 3.141
InstancejGroup.job1_2of DumbJob says: Hello World! and val is: 3.141


 Trigger

        Trigger对象是用来触发执行Job的。当调度一个job时,我们实例一个触发器然后调整它的属性来满足job执行的条件。触发器也有一个和它相关的JobDataMap,它是用来给被触发器触发的job传参数的。Quartz有一些不同的触发器类型,不过,用得最多的是SimpleTrigger和CronTrigger。

        如果我们需要在给定时刻执行一次job或者在给定时刻触发job随后间断一定时间不停的执行的话,SimpleTrigger是个简单的解决办法;如果我们想基于类似日历调度的触发job的话,比如说,在每个星期五的中午或者在每个月第10天的10:15触发job时,CronTrigger是很有用的。

         为什么用jobs和triggers呢?很多任务调度器并没有任务和触发器的概念,一些任务调度器简单定义一个“job”为在一个执行时间伴随一些小任务标示,其他的更像Quartz里job和trigger对象的联合体。在开发Quartz时,开发者们决定,在调度时间表和在这上面运行的工作应该分开。这是很有用的。

        例如,job能够独立于触发器被创建和储存在任务调度器里,并且,很多的触发器能够与同一个job关联起来。这个松耦合的另一个好处就是在与jobs关联的触发器终止后,我们能够再次配置保留在调度器里的jobs,这样的话,我们能够再次调度这些jobs而不需要重新定义他们。我们也可以在不重新定义一个关联到job的触发器的情况下,修改或替代它。

         当Jobs和triggers被注册到Quartz的调度器里时,他们就有了唯一标示符。他们也可以被放到“groups”里,Groups是用来组织分类jobs和triggers的,以便今后的维护。在一个组里的job和trigger的名字必须是唯一的,换句话说,一个job和trigger的全名为他们的名字加上组名。如果把组名置为”null”,系统会自动给它置为Scheduler.DEFAULT_GROUP

Scheduler在使用之前需要实例化。一般通过SchedulerFactory来创建一个实例。有些用户将factory的实例保存在JNDI中,但直接初始化,然后使用该实例也许更简单(见下面的示例)。

scheduler实例化后,可以启动(start)、暂停(stand-by)、停止(shutdown)。注意:scheduler被停止后,除非重新实例化,否则不能重新启动;只有当scheduler启动后,即使处于暂停状态也不行,trigger才会被触发(job才会被执行)。


SimpleTrigger的介绍

正如其名所示,SimpleTrigger对于设置和使用是最为简单的一种 QuartzTrigger。它是为那种需要在特定的日期/时间启动,且以一个可能的间隔时间重复执行 n 次的 Job 所设计的。
我们前面已经在一个简单的Quartz的例子里使用过了SimpleTrigger,我们通过:

SimpleScheduleBuilder builder=SimpleScheduleBuilder.simpleSchedule()          //设置间隔执行时间          .withIntervalInSeconds(5)          //设置执行次数          .withRepeatCount(4);  Trigger trigger=TriggerBuilder.newTrigger().withIdentity(                  "trigger1_1","tGroup1").startNow().withSchedule(builder).build();
或者无限执行
        SimpleScheduleBuilder builder=SimpleScheduleBuilder.simpleSchedule()              //设置间隔执行时间              .withIntervalInSeconds(5)              //设置执行次数              .repeatForever();                  Trigger trigger=TriggerBuilder.newTrigger().withIdentity(                      "trigger1_1","tGroup1").startNow().withSchedule(builder).build();  
对于Quartz而言,它还不能满足我们的触发情况,所以它仅仅是用于一些简单的触发情况;

CronTrigger

        CronTrigger 允许设定非常复杂的触发时间表。然而有时也许不得不使用两个或多个 SimpleTrigger来满足你的触发需求,这时候,你仅仅需要一个 CronTrigger 实例就够了。顾名思义,CronTrigger 是基于 Unix类似于 cron 的表达式。例如,你也许有一个 Job,要它在星期一和星期五的上午 8:00-9:00间每五分钟执行一次。假如你试图用 SimpleTrigger 来实现,你或许要为这个 Job 配置多个Trigger。然而,你可以使用如下的表达式来产生一个遵照这个时间表触发的 Trigger;
比如:

// 创建Trigger  CronScheduleBuilder builder2 = CronScheduleBuilder.cronSchedule("0 0/5 8 * * *");//8:00-8:55,每隔5分钟执行  /** builder2 = CronScheduleBuilder.dailyAtHourAndMinute(12, 30); **/  Trigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger1_1","tGroup1").startNow().withSchedule(builder2).build();  

Job与Trigger的关系

        大家都知道,一个作业,比较重要的三个要素就是Schduler,jobDetail,Trigger;而Trigger对于job而言就好比一个驱动器;没有触发器来定时驱动作业,作业就无法运行;对于Job而言,一个job可以对应多个Trigger,但对于Trigger而言,一个Trigger只能对应一个job;所以一个Trigger 只能被指派给一个 Job;如果你需要一个更复杂的触发计划,你可以创建多个 Trigger 并指派它们给同一个 Job。


参考地址:http://blog.csdn.net/evankaka/article/details/45361759









原创粉丝点击