Quartz框架之Job和JobDetail(2)

1 无状态任务

由上章节可知,Job接口是具体的任务逻辑类必须要实现的接口

public class HelloJob  implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        StringJoiner joiner=new StringJoiner(" ")
                .add("hello")
                .add(DateUtil.getDateTime(new Date()))
                .add(Thread.currentThread().getName())
                .add(jobExecutionContext.getTrigger().getKey().getName());

        System.out.println(joiner.toString());
    }
}

在JobBuilder创建JobDetail实例时,我们通过传递任务类型的方式告知触发器将要触发的任务。

// newJob方法是JobBuilder类提供的静态方法
 JobDetail job = newJob(HelloJob.class)
                 .withIdentity("job1", "group1")
                 .build();

每次触发时,通过任务类型的无参数构造函数实例化HelloJob 对象,然后再执行实例对象中的execute方法。任务结束后,这个任务实例对象将被垃圾回收器回收。
为了演示每次触发时,quartz框架都会重新创建任务实例,HelloJob中增加无参数构造方法

 public HelloJob(){
        System.out.println("我被构造了"+this.hashCode());
    }

同样使用上篇文章中的代码样例 quartz(1),此时控制台输出

2022-09-26 19:36:24.546  INFO 2212 ---
我被构造了10703978
hello 2022-09-26 19:36:24
我被构造了10692626
hello 2022-09-26 19:36:27
我被构造了22832069
hello 2022-09-26 19:36:30
我被构造了9617674
hello 2022-09-26 19:36:33
我被构造了14815745
hello 2022-09-26 19:36:36
.......

通过输出可知每次调用execute前,均先实例化HelloJob对象【不是同一个对象,hashcode码不一样】。无参数构造方法意味着HelloJob任务的执行中不包含任务的信息,意味着这是一个无状态的任务

2 有状态任务

与任务的执行过程中,不包含任何外来的参数信息相反,有状态任务意味着任务的执行需要外部的条件,比如有一个高温预警任务,需要判定当前温度是否为高温(大于39摄氏度),并决定是否发送短信通知。这里就有一个参数决定任务的执行逻辑,当前温度。显然我们只能通过无参数构造的方法实例化任务逻辑对象,但是我们可以用JobDataMap存放Job执行的外部信息。

JobDataMap 可用于保存您希望在作业实例执行时可供其使用的任意数量的(可序列化)数据对象。JobDataMap 是 Java 映射接口的实现,并且增加了一些用于存储和检索基元类型数据的便捷方法。
JobDetail和Trigger中都可以包含自己的JobDataMap

实例代码如下


public class HelloDataJobimplements Job {
   @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        StringJoiner joiner=new StringJoiner(" ")
                .add("hello every one")
                .add("I am "+jobExecutionContext.getJobDetail().getJobDataMap().get("name"))
                .add("I am "+jobExecutionContext.getJobDetail().getJobDataMap().get("age"))
                .add(DateUtil.getDateTime(new Date()))
                .add("triggered by "+jobExecutionContext.getTrigger().getJobDataMap().get("trigger_name"));

        System.out.println(joiner.toString());
    }
}
    @Test
    void moreAboutJob(){
        try {
            // Grab the Scheduler instance from the Factory
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

            // and start it off
            scheduler.start();


            // define the job and tie it to our HelloJob class
            JobDetail job = newJob(HelloDataJob.class)
                    .withIdentity("job1", "group1")
                    .usingJobData("name","lyf")
                    .usingJobData("age",19)
                    .build();

            // Trigger the job to run now, and then repeat every 40 seconds
            Trigger trigger = newTrigger()
                    .withIdentity("trigger1", "group1")
                    .usingJobData("trigger_name","trigger1")
                    .startNow()
                    .withSchedule(simpleSchedule()
                            .withIntervalInSeconds(3)
                            .repeatForever())
                    .build();

            // Tell quartz to schedule the job using our trigger
            scheduler.scheduleJob(job, trigger);

            Thread.sleep(10000);
            scheduler.shutdown();

        } catch (SchedulerException | InterruptedException se) {
            se.printStackTrace();
        }
   }
hello every one I am lyf I am 19 2022-09-26 20:29:42 triggered by trigger1
hello every one I am lyf I am 19 2022-09-26 20:29:45 triggered by trigger1
hello every one I am lyf I am 19 2022-09-26 20:29:48 triggered by trigger1
hello every one I am lyf I am 19 2022-09-26 20:29:51 triggered by trigger1

3 Job和JobDetail的关系

首先得出结论,一个Job可被多个JobDetail同时引用,每个JobDetail中可存放具体实例定义的信息。这样设计的原因在于,每个任务逻辑执行的条件可能不同,那么就必须根据实际情形描述每个任务执行的其他信息。

比如,你可以创建一个类来实现名为“销售报告作业”的作业。可以对作业进行编码,以期望发送给它的参数(通过 JobDataMap)指定销售报表应基于的销售人员的姓名。然后,他们可以创建作业的多个定义(工作详细信息),例如“Joe”和“mike”

当触发器触发时,将加载它所关联的 JobDetail(实例定义),并通过计划程序上配置的 JobFactory 实例化它所引用的作业类。默认的作业工厂只是在作业类上调用 newInstance(),然后尝试调用与 JobDataMap 中的键名称匹配的类上的 setter 方法。也可能希望创建自己的 JobFactory 实现来完成一些事情,例如让应用程序的 IoC 或 DI 容器生成/初始化作业实例。

你可能感兴趣的:(quartz定时框架,java,quartz)