咱们明天剖析Quartz中与作业相干的3个概念:

  1. Job
  2. JobDetail
  3. JobDataMap

Job

上一篇文章曾经简略做过剖析:Job是工作接口,蕴含一个execute办法。Job与JDK Timer中的TimerTask相似,是提供给利用实现工作逻辑的API。

应用层须要关注的其实就是这个Job接口,作业须要实现的业务逻辑就在Job接口的实现类的execute办法中实现。

JobDetail

JobDetail用来持有Job实现类的类名,最终绑定到任务调度器中的不是Job而是JobDetail。JobDetail接口不须要利用关怀、也不须要应用层实现,Quartz提供了一个JobDetail的实现类JobDetailImpl,通过JobBuilder来创立。

JobDetail有一个类型为JobKey的重要属性key,相当于是该工作的键值,JobDetail注册到任务调度器Schedule中的时候,key值不容许反复。整个任务调度过程中,Quartz都是通过Jobkey来惟一辨认JobDetail的。试图将反复键值的JobDetail注册到任务调度器中而不指定笼罩的话,是不被容许的。

JobKey能够通过JobBuiler的withIdentity办法指定,该办法接管name或name+group参数,从而惟一确定一个工作JobDetail。

如果在JobDetail创立过程中不指定JobKey的话,Quartz会通过UUID的形式为该工作生成一个惟一的key值。

所以,同一个Job实现类(也就是同一个工作),能够通过不同的JobKey值注册到任务调度器中、绑定不同的触发器执行!

Job的调度形式

Quartz的工作执行线程在调度Job工作的时候,是通过JobDetail持有的Job实现类的类名调用newInstance办法创立新的对象来实现的:

JobDetailImpl为什么会持有Job实现类的类名、而不是间接持有Job对象、通过该对象间接执行工作?

集体认为这么做的目标之一是为了实现多线程任务调度过程中Job的线程安全性。因为如果间接持有Job实现类的对象的话,就意味着每次任务调度器触发并执行该工作的时候,都是通过雷同的Job实现类的对象来执行工作的,则Job实现类的状态肯定是当前任务执行实现之后的状态,这样的话就要求客户端程序员务必关注对Job实现类状态的解决,稍有不慎可能就会导致意想不到的后果。

每一个工作线程都是通过新的工作对象来执行工作,也能够防止多线程任务调度过程中的工作安全性问题。

这种实现形式其实也要求咱们的Job实现类必须提供无参结构器,否则Quartz在创立工作对象的时候会抛出SchedulerException异样。

JobDataMap

JobDataMap是不限个数的一组数据集,能够通过JobDataMap在创立工作的时候传递参数给该工作、在工作执行的时候能够获取到该数据集。

比方咱们后面说过,一个Job实现类能够通过创立多个不同的JobDetail(通过不同的JobKey辨别)绑定到任务调度器schedule中,这种状况下能够就通过JobDataMap传递不同的参数给JobDetail从而辨别他们的行为。Quartz官网中举例说明的“SalesReportForJoe”、“SalesReportForMike”就是这个意思。

举例:

public class HelloJob implements Job {    @Override    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {      log.info("I dont know want should i do ..."+Thread.currentThread().getId()+                " and I am :" + this + " and jobname="+jobExecutionContext.getJobDetail().getKey());      JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();      if(jobDataMap!=null){           log.info("JD:"+jobDataMap.get("JD"));      }    }    public static void main(String[] args) {        log.info("I am running...");        JobDetail jobDetail = newJob(HelloJob.class)                .withDescription("This is my first quartz job")                .usingJobData("JD","This is JD")                .withIdentity("MyJob")                .build();        JobDetail jobDetail1 = newJob(HelloJob.class)                .withDescription("This is my first quartz job")                .usingJobData("JD","This is JD1")                .withIdentity("MyJob1")                .build();        Trigger trigger = newTrigger()                .withIdentity("myTriggger","MyGroup")                .startNow()                .withSchedule(simpleSchedule()                        .withIntervalInSeconds(20)                        .repeatForever())                .build();        Trigger trigger1 = newTrigger()                .withIdentity("myTriggger1","MyGroup1")                .startNow()                .withSchedule(simpleSchedule()                        .withIntervalInSeconds(20)                        .repeatForever())                .build();        try {            Scheduler sche = new StdSchedulerFactory().getScheduler();            sche.scheduleJob(jobDetail,trigger);            sche.scheduleJob(jobDetail1,trigger1);            sche.start();        }catch(Exception e){            e.printStackTrace();        }        log.info("i am done");    }}

创立HelloJob实现Job接口的execute办法,该办法只是打印以后作业的线程id、以后Job对象、以及获取到的JobDataMap。

运行后果:

22:32:36.974 [DefaultQuartzScheduler_Worker-1] INFO com.example.demo.quartz.HelloJob - I dont know want should i do ...11 and I am :com.example.demo.quartz.HelloJob@77e596d4 and jobname=DEFAULT.MyJob22:32:36.974 [DefaultQuartzScheduler_Worker-1] INFO com.example.demo.quartz.HelloJob - JD:This is JD22:32:36.974 [DefaultQuartzScheduler_Worker-2] INFO com.example.demo.quartz.HelloJob - I dont know want should i do ...12 and I am :com.example.demo.quartz.HelloJob@239bdf36 and jobname=DEFAULT.MyJob122:32:36.974 [DefaultQuartzScheduler_Worker-2] INFO com.example.demo.quartz.HelloJob - JD:This is JD120秒后:22:32:56.830 [DefaultQuartzScheduler_Worker-3] INFO com.example.demo.quartz.HelloJob - I dont know want should i do ...13 and I am :com.example.demo.quartz.HelloJob@78a13114 and jobname=DEFAULT.MyJob22:32:56.830 [DefaultQuartzScheduler_Worker-3] INFO com.example.demo.quartz.HelloJob - JD:This is JD22:32:56.831 [DefaultQuartzScheduler_Worker-4] INFO com.example.demo.quartz.HelloJob - I dont know want should i do ...14 and I am :com.example.demo.quartz.HelloJob@1a9fa98f and jobname=DEFAULT.MyJob122:32:56.831 [DefaultQuartzScheduler_Worker-4] INFO com.example.demo.quartz.HelloJob - JD:This is JD1

从运行后果咱们能够失去以下论断:

  1. Quartz每次从线程池获取不同的线程来执行工作。
  2. 每次任务调度时,执行工作的Job对象不同。
  3. 绑定工作到任务调度器时,批准通过设置JobDataMap传递参数到工作对象,在工作执行时能获取到改参数。
  4. 一个Job实现类能够通过不同的JobDetail屡次绑定到同一个任务调度器的不同触发器上,从而被不同的触发规定触发执行。

上一篇 Quartz - SimpleThreadPool