Quartz(1-Job)
|总字数:2.8k|阅读时长: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
| 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中存储的数据很可能是不确定的。
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); } }
|
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 ==============================
|