Quartz(1-Job)
|总字数:2.9k|阅读时长:12分钟|浏览量:|
基本使用
1 2 3 4 5
   | <dependency>     <groupId>org.quartz-scheduler</groupId>     <artifactId>quartz</artifactId>     <version>2.3.1</version> </dependency>
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
   | public class HelloJob implements Job {
      @Override     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {                  Date fireTime = jobExecutionContext.getFireTime();         System.out.println("fireTime:" + fireTime);                  Date previousFireTime = jobExecutionContext.getPreviousFireTime();         System.out.println("previousFireTime:" + previousFireTime);                  Date nextFireTime = jobExecutionContext.getNextFireTime();         System.out.println("nextFireTime:" + nextFireTime);                  Date scheduledFireTime = jobExecutionContext.getScheduledFireTime();         System.out.println("scheduledFireTime:" + scheduledFireTime);
          JobDetail jobDetail = jobExecutionContext.getJobDetail();         System.out.println("jobDataMap:" + JSON.toJSONString(jobDetail.getJobDataMap()));         System.out.println("jobKey:" + JSON.toJSONString(jobDetail.getKey()));         System.out.println("jobDescription:" + jobDetail.getDescription());         System.out.println("==================================");     }
      public static void main(String[] args) throws SchedulerException {                  JobDetail jobDetail = JobBuilder                 .newJob(HelloJob.class)                  .withIdentity("hello","group1")                 .withDescription("Quartz测试")                 .usingJobData("name", "小米")                 .usingJobData("age", 15)                 .build();
                   SimpleTrigger trigger = TriggerBuilder.newTrigger()                 .withIdentity("myTrigger", "group1")                 .startNow()                  .withSchedule(SimpleScheduleBuilder.simpleSchedule()                         .withIntervalInSeconds(2)                          .repeatForever())                  .build();                  StdSchedulerFactory factory = new StdSchedulerFactory();         Scheduler scheduler = factory.getScheduler();         scheduler.start();          scheduler.scheduleJob(jobDetail, trigger);      } }
  | 
 
JobExecutionContext
当 Scheduler 调用一个 Job 就会将 JobExecutionContext 传递给 Job 的 execute()方法,Job 能通过 JobExecutionContext 对象访问到 Quartz 运行时候的环境和 Job 本身的明细数据
JobDetail、JobBuilder
方法
- storeDurably
 
JobDetails 信息持久化到数据库的时候有一个属性 storeDurably,如果设置为 true 则无论与其关联的 Trigger 是否存在其都会一直存在,否则只要相关联的 trigger 删除掉了其会自动删除掉
- requestRecovery
 
请求恢复,也就是说当应用发生故障的时候,是否重新执行默认是 false。如果一个 job 是可恢复的,并且在其执行的时候,scheduler 发生硬关闭(hard shutdown)(比如运行的进程崩溃了,或者关机了),则当 scheduler 重新启动的时候,该 job 会被重新执行。此时,该 job 的 JobExecutionContext.isRecovering() 返回 true
- usingJobData、setJobData
 
添加 Job 数据,每个 JobDetail 内都有一个 JobDataMap,包含了关联到这个 Job 的数据,在 Job 类中,可以通过 context 取出该数据,进行业务流程处理。
- withIdentity
 
给 JobDetail 起一个 Id,方便后面检索
- withDescription
 
用来对 job 进行描述,并没有什么实际作用
JobKey
JobKey 是表明 Job 身份的一个对象,里面封装了 Job 的 name 和 group,TriggerKey 同理。当不指定 group 时,Quartz 会用默认的组名 DEFAULT
JobDataMap
JobDetail 是任务的定义,而 Job 是任务的执行逻辑,每一个 JobDetail 都会有一个 JobDataMap,JobDataMap 本质就是一个 Map 的扩展类,可以存储一些任务信息
JobDataMap 获取任务信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
   | public class HelloJob implements Job {
      @Override     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {         JobDetail jobDetail = jobExecutionContext.getJobDetail();         JobDataMap jobDataMap = jobDetail.getJobDataMap();         System.out.println("name:" + jobDataMap.getString("name"));         System.out.println("age:" + jobDataMap.getInt("age"));         System.out.println("jobKey:" + JSON.toJSONString(jobDetail.getKey()));         System.out.println("jobDescription:" + jobDetail.getDescription());         System.out.println("==================================");     }
      public static void main(String[] args) throws SchedulerException {                  JobDetail jobDetail = JobBuilder                 .newJob(HelloJob.class)                  .withIdentity("hello","group1")                 .withDescription("Quartz测试")                 .usingJobData("name", "小米")                 .usingJobData("age", 15)                 .build();
                   SimpleTrigger trigger = TriggerBuilder.newTrigger()                 .withIdentity("myTrigger", "group1")                 .startNow()                  .withSchedule(SimpleScheduleBuilder.simpleSchedule()                         .withIntervalInSeconds(2)                          .repeatForever())                  .build();                  StdSchedulerFactory factory = new StdSchedulerFactory();         Scheduler scheduler = factory.getScheduler();         scheduler.start();          scheduler.scheduleJob(jobDetail, trigger);      } }
  | 
 
实体类获取任务信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
   | public class HelloJob3 implements Job {
      private String message;     private Float floatJobValue;     private Double doubleTriggerValue;
      public String getMessage() {         return message;     }
      public void setMessage(String message) {         this.message = message;     }
      public Float getFloatJobValue() {         return floatJobValue;     }
      public void setFloatJobValue(Float floatJobValue) {         this.floatJobValue = floatJobValue;     }
      public Double getDoubleTriggerValue() {         return doubleTriggerValue;     }
      public void setDoubleTriggerValue(Double doubleTriggerValue) {         this.doubleTriggerValue = doubleTriggerValue;     }
      @Override     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {                  Date date = new Date();         SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");         System.out.println("现在的时间是:" + sf.format(date));                  System.out.println("jobDataMap定义的message的值 : " + message);                  System.out.println("jobDataMap定义的floatJobValue的值 : " + floatJobValue);    		System.out.println("==================================");     }
      public static void main(String[] args) throws SchedulerException {                  JobDetail jobDetail = JobBuilder                 .newJob(HelloJob3.class)                  .withIdentity("myJob", "group1")                  .usingJobData("message","hello myJob1")                  .usingJobData("FloatJobValue",8.88f)                  .build();
                   SimpleTrigger trigger = TriggerBuilder.newTrigger()                 .withIdentity("myTrigger", "group1")                 .startNow()                  .withSchedule(SimpleScheduleBuilder.simpleSchedule()                         .withIntervalInSeconds(2)                          .repeatForever())                  .build();                  StdSchedulerFactory factory = new StdSchedulerFactory();         Scheduler scheduler = factory.getScheduler();         scheduler.start();          scheduler.scheduleJob(jobDetail,trigger);      } }
  | 
 
注解使用
@PersistJobDataAfterExecution
有状态的 Job 可以理解为多次 Job 调用期间可以持有一些状态信息,这些状态信息存储在 JobDataMap 中,而默认的无状态 Job 每次调用时都会创建一个新的 JobDataMap
注意:没有添加@PersistJobDataAfterExecution 注解,每次调用时都会创建一个新的 JobDataMap,不会累加;添加该注解后,多次调用期间可以持有一些状态信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
   | @PersistJobDataAfterExecution public class HelloJob4 implements Job {
      private Integer count;
      public void setCount(Integer count) {         this.count = count;     }
      @Override     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {         System.out.println(++count);         jobExecutionContext.getJobDetail().getJobDataMap().put("count", count);     }
      public static void main(String[] args) throws SchedulerException {                  JobDetail jobDetail = JobBuilder                 .newJob(HelloJob4.class)                  .withIdentity("myJob", "group1")                  .usingJobData("count",0)                  .build();
                   SimpleTrigger trigger = TriggerBuilder.newTrigger()                 .withIdentity("myTrigger", "group1")                 .startNow()                  .withSchedule(SimpleScheduleBuilder.simpleSchedule()                         .withIntervalInSeconds(2)                          .repeatForever())                  .build();                  StdSchedulerFactory factory = new StdSchedulerFactory();         Scheduler scheduler = factory.getScheduler();         scheduler.start();          scheduler.scheduleJob(jobDetail,trigger);      } }
   | 
 
@DisallowConcurrentExecution
禁止并发执行多个相同定义的 JobDetail,这个注解是加在 Job 类上的,但意思并不是不能同时执行多个 Job,而是不能并发执行同一个 Job
例如:同一个 Job 实现类 DemoJob 的两个 JobDetail 实例 A 和 B,设置 A 的定时执行频率为每 1 分钟执行一次,A 的实际运行耗时为 3 分钟,B 的定时执行频率也是每 1 分钟执行一次,B 的实际运行耗时为 30 秒。假如在 07:00 分 00 秒时 A 和 B 同时第一次运行,则到 07:00 分 30 秒时 B 运行结束,此时 A 还在运行中,到 07:01 分 00 秒时 A 和 B 又该执行了,但是由于注解@DisallowConcurrentExecution 的缘故,此时 A 不会再次运行,A 只能在其上一次运行结束后才能再次被调用执行。但是 B 会正常运行(B 不受 A 的影响,注解@DisallowConcurrentExecution 是作用于 JobDetail 实例而不是 Job 实现类)
注意:如果你使用了@PersistJobDataAfterExecution 注解,则强烈建议你同时使用@DisallowConcurrentExecution 注解,因为当同一个 job(JobDetail)的两个实例被并发执行时,由于竞争,JobDataMap 中存储的数据很可能是不确定的。
使用同一个Job对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
   | @DisallowConcurrentExecution public class HelloJob5 implements Job {
      @Override     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {         Date date = new Date();         SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");         System.out.println("现在的时间是:" + sf.format(date));         JobKey key = jobExecutionContext.getJobDetail().getKey();                  System.out.println("jobDetail 的name : " + key.getName());                  System.out.println("jobDetail 的group : " + key.getGroup());         System.out.println("==============================");         try {             Thread.sleep(3000);         } catch (InterruptedException e) {             throw new RuntimeException(e);         }     }
      public static void main(String[] args) throws SchedulerException {                  JobDetail jobDetail1 = JobBuilder                 .newJob(HelloJob5.class)                  .withIdentity("group1", "group1")                  .build();
                   SimpleTrigger trigger1 = TriggerBuilder.newTrigger()                 .withIdentity("myTrigger1", "group1")                 .startNow()                  .withSchedule(SimpleScheduleBuilder.simpleSchedule()                         .withIntervalInSeconds(2)                          .repeatForever())                  .build();                  StdSchedulerFactory factory = new StdSchedulerFactory();         Scheduler scheduler = factory.getScheduler();         scheduler.start();          scheduler.scheduleJob(jobDetail1, trigger1);      } }
   | 
 
- 使用@DisallowConcurrentExecution前
 
1 2 3 4 5 6 7 8 9 10 11 12 13
   |  现在的时间是:2024-11-12 00:59:49 jobDetail 的name : group1 jobDetail 的group : group1 ============================== 现在的时间是:2024-11-12 00:59:52 jobDetail 的name : group1 jobDetail 的group : group1 ============================== 现在的时间是:2024-11-12 00:59:55 jobDetail 的name : group1 jobDetail 的group : group1 ==============================
 
  | 
 
- 使用@DisallowConcurrentExecution后
 
1 2 3 4 5 6 7 8 9 10 11 12 13
   |  现在的时间是:2024-11-12 01:00:48 jobDetail 的name : group1 jobDetail 的group : group1 ============================== 现在的时间是:2024-11-12 01:00:50 jobDetail 的name : group1 jobDetail 的group : group1 ============================== 现在的时间是:2024-11-12 01:00:52 jobDetail 的name : group1 jobDetail 的group : group1 ==============================
 
  | 
 
创建两个 Job 对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
   | @DisallowConcurrentExecution public class HelloJob5 implements Job {
      @Override     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {         Date date = new Date();         SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");         System.out.println("现在的时间是:" + sf.format(date));         JobKey key = jobExecutionContext.getJobDetail().getKey();                  System.out.println("jobDetail 的name : " + key.getName());                    System.out.println("jobDetail 的group : " + key.getGroup());             System.out.println("==============================");         try {             Thread.sleep(3000);         } catch (InterruptedException e) {             throw new RuntimeException(e);         }     }
      public static void main(String[] args) throws SchedulerException {                  JobDetail jobDetail1 = JobBuilder                 .newJob(HelloJob5.class)                  .withIdentity("group1", "group1")                  .build();
                   SimpleTrigger trigger1 = TriggerBuilder.newTrigger()                 .withIdentity("myTrigger1", "group1")                 .startNow()                  .withSchedule(SimpleScheduleBuilder.simpleSchedule()                         .withIntervalInSeconds(2)                          .repeatForever())                  .build();                  StdSchedulerFactory factory = new StdSchedulerFactory();         Scheduler scheduler = factory.getScheduler();         scheduler.start();          scheduler.scheduleJob(jobDetail1, trigger1); 
          JobDetail jobDetail2 = JobBuilder                 .newJob(HelloJob5.class)                  .withIdentity("group2", "group2")                  .build();
                   SimpleTrigger trigger2 = TriggerBuilder.newTrigger()                 .withIdentity("myTrigger2", "group2")                 .startNow()                  .withSchedule(SimpleScheduleBuilder.simpleSchedule()                         .withIntervalInSeconds(3)                          .repeatForever())                  .build();                  Scheduler scheduler2 = factory.getScheduler();         scheduler2.start();          scheduler2.scheduleJob(jobDetail2, trigger2);      } }
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   |  现在的时间是:2024-11-12 01:08:37 现在的时间是:2024-11-12 01:08:37 jobDetail 的name : group2 jobDetail 的name : group1 jobDetail 的group : group1 jobDetail 的group : group2 ============================== ============================== 现在的时间是:2024-11-12 01:08:40 jobDetail 的name : group2 jobDetail 的group : group2 ============================== 现在的时间是:2024-11-12 01:08:40 jobDetail 的name : group1 jobDetail 的group : group1 ==============================
 
  |