Quartz学习---入门demo【任务调度的运行信息在内存】(一)
2018-03-09 14:57
736 查看
定时任务经常使用,从未研究其内部原理等。实际项目中多机部署时遇到问题,项目部署在不同服务器上。同一时间同时启动怕出现错误。于是有了此篇文章。
首先先从简单的demo入手(log4j.properties未配置,任务调度的运行信息在内存):
使用SimpleTrigger
1. 新建了一个Java类让它实现quartz的job方法,这就是一个简单的job。
2.Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。因此我们还需要创建一个JobDetail实例并且指定是那个job.最后定义我们的触发规则类,只有触发规则和我们的job关联起来才能实现我们想要的功能。
执行结果: 刚启动有一次定义了三次共4次
在定义jobDetail和Trigger时我们可以指定其名称已经其所属组的名称像这样定义:
scheduler 执行 job 时,在调用其 execute() 方法之前会创建该类的一个新的实例,执行完毕,该实例的饮用就会被丢弃,实例会被垃圾回收。这种执行策略带来的后果就是,job 必须有一个无参的构造函数;另一个是,在 job 类中,不应该定义有状态的数据属性,因为 job 多次执行中,这些属性的值不会保留。
那么如何给 job 实例增加属性或配置呢?如何在 job 多次执行中,跟踪 job 的状态呢?答案就是 JobDataMap。我们在job加入调度之前可以将一些数据放入JobDataMap中在job执行的过程中我们就可以取出来使用。JobDataMap是map的一个实现,所以我们可以用键值对方式对其进行操作。
例如:
Trigger定义
结果:
使用CronTrigger
CronTrigger 能够提供比 SimpleTrigger 更有具体实际意义的调度方案,调度规则基于 Cron
表达式,CronTrigger
支持日历相关的重复时间间隔(比如每月第一个周一执行),而不是简单的周期时间间隔。因此,相对于SimpleTrigger而言,CronTrigger在使用上也要复杂一些。
Cron表达式
Quartz使用类似于Linux下的Cron表达式定义时间规则,Cron表达式由6或7个由空格分隔的时间字段组成,如表1所示: 表1
Cron表达式时间字段
Cron表达式的时间字段除允许设置数值外,还可使用一些特殊的字符,提供列表、范围、通配符等功能,细说如下:
●星号():可用在所有字段中,表示对应时间域的每一个时刻,例如,在分钟字段时,表示“每分钟”;
●问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符;
●减号(-):表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12;
●逗号(,):表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五;
●斜杠(/):x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y;
●L:该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示星期六,等同于7。但是,如果L出现在星期字段里,而且在前面有一个数值X,则表示“这个月的最后X天”,例如,6L表示该月的最后星期五;
●W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号是星期二,那结果就是15号星期二。但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。W字符串只能指定单一日期,而不能指定日期范围;
●LW组合:在日期字段可以组合使用LW,它的意思是当月的最后一个工作日;
●井号(#):该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发;
●
C:该字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。
Cron表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。
实例如下:
结果:
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
2018-03-09 13:48:00Hello Quartz!
jobGroup.simpleJob
key=String value=哈哈哈
key=int value=12
key=boolean value=true
使用Calendar
实际任务调度中我们除了这种周期性的任务调度以外,还需要有些特殊的情况。例如每天下午1点48执行但是周五不执行,遇到这种情况就需要我们使用Calendar。下面是calendar中各个类的用法
实例如下:
public class CronTriggerWithCalendarDemo {
}
首先先从简单的demo入手(log4j.properties未配置,任务调度的运行信息在内存):
使用SimpleTrigger
1. 新建了一个Java类让它实现quartz的job方法,这就是一个简单的job。
/** * 简单的job类 * */ public class SimpleJob implements Job{ @Override public void execute(JobExecutionContext jobContext) throws JobExecutionException { System.out.println("jobContext.getTrigger():"+jobContext.getTrigger().getJobDataMap()+"时间"+new Date()); } }
2.Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。因此我们还需要创建一个JobDetail实例并且指定是那个job.最后定义我们的触发规则类,只有触发规则和我们的job关联起来才能实现我们想要的功能。
public class SimpleTrigger { public static void main(String[] args) throws SchedulerException { // 定义一个jobDetail JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class).build(); // 定义一个触发规则每5秒触发一次总计3次 Trigger trigger = TriggerBuilder.newTrigger() .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(5).withRepeatCount(3)) .build(); //通过SchedulerFactory获取一个调度器实例 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.scheduleJob(jobDetail, trigger); //启动调度 scheduler.start(); } }
执行结果: 刚启动有一次定义了三次共4次
log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. 2018-03-09 10:56:38Hello Quartz! 2018-03-09 10:56:43Hello Quartz! 2018-03-09 10:56:48Hello Quartz! 2018-03-09 10:56:53Hello Quartz!
在定义jobDetail和Trigger时我们可以指定其名称已经其所属组的名称像这样定义:
// 定义一个jobDetail JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class).withIdentity("simpleJob", "jobGroup").build(); // 定义一个触发规则每5秒触发一次总计3次 Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("simpleTriggeer", "jobTriggerGroup") .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(5).withRepeatCount(3)) .build();
scheduler 执行 job 时,在调用其 execute() 方法之前会创建该类的一个新的实例,执行完毕,该实例的饮用就会被丢弃,实例会被垃圾回收。这种执行策略带来的后果就是,job 必须有一个无参的构造函数;另一个是,在 job 类中,不应该定义有状态的数据属性,因为 job 多次执行中,这些属性的值不会保留。
那么如何给 job 实例增加属性或配置呢?如何在 job 多次执行中,跟踪 job 的状态呢?答案就是 JobDataMap。我们在job加入调度之前可以将一些数据放入JobDataMap中在job执行的过程中我们就可以取出来使用。JobDataMap是map的一个实现,所以我们可以用键值对方式对其进行操作。
例如:
public class SimpleJob implements Job{ @Override public void execute(JobExecutionContext jobContext) throws JobExecutionException { System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") .format(new Date())+"Hello Quartz!"); /*JobKey jobKey = jobContext.getJobDetail().getKey(); JobDataMap dataMap = jobContext.getJobDetail().getJobDataMap(); int num = dataMap.getInt("int"); String str = dataMap.getString("String"); boolean boo = dataMap.getBoolean("boolean"); System.err.println(num+"==="+num);*/ JobKey jobTriggerKey = jobContext.getTrigger().getJobKey(); JobDataMap triggerDataMap = jobContext.getTrigger().getJobDataMap(); Iterator<Entry<String, Object>> it = triggerDataMap.entrySet().iterator(); System.out.println(jobTriggerKey); while (it.hasNext()) { Entry<String, Object> entry = it.next(); Object key = entry.getKey(); Object value = entry.getValue(); System.out.println("key=" + key + " value=" + value); } } }
Trigger定义
public class SimpleTrigger { public static void main(String[] args) throws SchedulerException { // 定义一个jobDetail JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class).withIdentity("simpleJob", "jobGroup").build(); // 定义一个触发规则每5秒触发一次总计3次 Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("simpleTriggeer", "jobTriggerGroup") .usingJobData("int", 12) .usingJobData("String", "哈哈哈") .usingJobData("boolean", true) .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(5).withRepeatCount(0)) .build(); //通过SchedulerFactory获取一个调度器实例 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.scheduleJob(jobDetail, trigger); //启动调度 scheduler.start(); } }
结果:
log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. 2018-03-09 11:29:30Hello Quartz! jobGroup.simpleJob key=String value=哈哈哈 key=int value=12 key=boolean value=true
使用CronTrigger
CronTrigger 能够提供比 SimpleTrigger 更有具体实际意义的调度方案,调度规则基于 Cron
表达式,CronTrigger
支持日历相关的重复时间间隔(比如每月第一个周一执行),而不是简单的周期时间间隔。因此,相对于SimpleTrigger而言,CronTrigger在使用上也要复杂一些。
Cron表达式
Quartz使用类似于Linux下的Cron表达式定义时间规则,Cron表达式由6或7个由空格分隔的时间字段组成,如表1所示: 表1
Cron表达式时间字段
Cron表达式的时间字段除允许设置数值外,还可使用一些特殊的字符,提供列表、范围、通配符等功能,细说如下:
●星号():可用在所有字段中,表示对应时间域的每一个时刻,例如,在分钟字段时,表示“每分钟”;
●问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符;
●减号(-):表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12;
●逗号(,):表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五;
●斜杠(/):x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y;
●L:该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示星期六,等同于7。但是,如果L出现在星期字段里,而且在前面有一个数值X,则表示“这个月的最后X天”,例如,6L表示该月的最后星期五;
●W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号是星期二,那结果就是15号星期二。但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。W字符串只能指定单一日期,而不能指定日期范围;
●LW组合:在日期字段可以组合使用LW,它的意思是当月的最后一个工作日;
●井号(#):该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发;
●
C:该字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。
Cron表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。
实例如下:
public class CronTriggerDemo { public static void main(String[] args) throws SchedulerException { // 定义一个jobDetail JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class).withIdentity("simpleJob", "jobGroup").build(); CronTrigger cronTrigger = (CronTrigger) TriggerBuilder.newTrigger() .withIdentity("cronTriggeer", "jobTriggerGroup") .usingJobData("int", 12) .usingJobData("String", "哈哈哈") .usingJobData("boolean", true) //每天下午1点48执行一次 .withSchedule(CronScheduleBuilder.cronSchedule("0 48 13 * * ?")) .build(); //通过SchedulerFactory获取一个调度器实例 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.scheduleJob(jobDetail, cronTrigger); //启动调度 scheduler.start(); } }
结果:
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
2018-03-09 13:48:00Hello Quartz!
jobGroup.simpleJob
key=String value=哈哈哈
key=int value=12
key=boolean value=true
使用Calendar
实际任务调度中我们除了这种周期性的任务调度以外,还需要有些特殊的情况。例如每天下午1点48执行但是周五不执行,遇到这种情况就需要我们使用Calendar。下面是calendar中各个类的用法
实例如下:
public class CronTriggerWithCalendarDemo {
public static void main(String[] args) throws SchedulerException { //通过SchedulerFactory获取一个调度器实例 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); // 定义一个jobDetail JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class).withIdentity("simpleJob", "jobGroup").build(); //定义一个Calendar WeeklyCalendar fridayCalendar = new WeeklyCalendar(); fridayCalendar.setDayExcluded(6, true); //注册Calendar scheduler.addCalendar("fridayCalendar", fridayCalendar, true, true); CronTrigger cronTrigger = (CronTrigger) TriggerBuilder.newTrigger() .withIdentity("cronTriggeer", "jobTriggerGroup") .modifiedByCalendar("fridayCalendar") .usingJobData("int", 12) .usingJobData("String", "哈哈哈") .usingJobData("boolean", true) //每天下午1点48执行一次 .withSchedule(CronScheduleBuilder.cronSchedule("0 48 14 * * ?")) .build(); scheduler.scheduleJob(jobDetail, cronTrigger); //启动调度 scheduler.start(); }
}
相关文章推荐
- 任务调度Quartz初探Demo(二)
- Quartz任务调度快速入门
- Quartz任务调度快速入门
- Quartz任务调度快速入门
- Quartz-任务调度概述及Quartz(2.2.X)快速入门
- spring学习笔记(26)spring整合Quartz2持久化稳健任务调度
- JavaEE进阶知识学习-----定时任务调度Quartz-2
- Quartz学习——Quartz简单入门Demo(二)
- Quartz.NET 2.0 学习笔记(5) :实例创建Windows服务实现任务调度
- 【Quartz】Quartz任务调度入门
- Quartz任务调度快速入门
- quartz任务调度整合springMVC学习一
- Quartz.NET 2.0 学习笔记(3) :通过配置文件实现任务调度
- Quartz任务调度快速入门
- 定时调度Quartz框架学习小demo
- 作业调度框架 Quartz 学习笔记(五) -- 错过的任务怎么办?
- Java任务调度开源框架quartz学习
- quartz 任务时间调度入门使用
- (转)Java任务调度框架Quartz入门教程指南(二) 使用job、trigger、schedule调用定时任务