Quartz 入门(1)
来源:互联网 发布:幸运28网站源码2016 编辑:程序博客网 时间:2024/06/04 19:18
1.简单介绍
Quartz相信有的朋友一定在写调度功能的时候听过,因为有些公司要做一些定时的任务,例如:定时生成报表,定时保存文件之类的。接下来就会简单实现一个入门级的Quartz小程序。不过在此之前,先来了解一下关于Quartz的基本概念。这里我就引用:http://blog.csdn.net/wenniuwuren 的一篇关于Quartz中的概念。
Quartz体系结构:
明白Quartz怎么用,首先要了解Scheduler(调度器)、Job(任务)和Trigger(触发器)这3个核心的概念。
<1>. Job: 是一个接口,只定义一个方法execute(JobExecutionContext context),在实现接口的execute方法中编写所需要定时执行的Job(任务), JobExecutionContext类提供了调度应用的一些信息。Job运行时的信息保存在JobDataMap实例中;
<3>. Trigger: 是一个类,描述触发Job执行的时间触发规则。主要有SimpleTrigger和CronTrigger这两个子类。当且仅当需调度一次或者以固定时间间隔周期执行调度,SimpleTrigger是最适合的选择;而CronTrigger则可以通过Cron表达式定义出各种复杂时间规则的调度方案:如工作日周一到周五的15:00~16:00执行调度等;
Cron表达式的格式:秒 分 时 日 月 周 年(可选)。
字段名 允许的值 允许的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日 1-31 , - * ? / L W C
月 1-12 or JAN-DEC , - * /
周几 1-7 or SUN-SAT , - * ? / L C # SUN, MON, TUE, WED, THU, FRI and SAT
年 (可选字段) empty, 1970-2099 , - * /
“?”字符:表示不确定的值
“,”字符:指定数个值
“-”字符:指定一个值的范围
“/”字符:指定一个值的增加幅度。n/m表示从n开始,每次增加m
“L”字符:用在日表示一个月中的最后一天,用在周表示该月最后一个星期X
“W”字符:指定离给定日期最近的工作日(周一到周五)
“#”字符:表示该月第几个周X。6#3表示该月第3个周五
Cron表达式范例:
每隔5秒执行一次:*/5 * * * * ?
每隔1分钟执行一次:0 */1 * * * ?
每天23点执行一次:0 0 23 * * ?
每天凌晨1点执行一次:0 0 1 * * ?
每月1号凌晨1点执行一次:0 0 1 1 * ?
每月最后一天23点执行一次:0 0 23 L * ?
每周星期天凌晨1点实行一次:0 0 1 ? * L
在26分、29分、33分执行一次:0 26,29,33 * * * ?
每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?
假设,我们安排每周星期一早上10:00执行任务,但是如果碰到法定的节日,任务则不执行,这时就需要在Trigger触发机制的基础上使用Calendar进行定点排除。针对不同时间段类型,Quartz在org.quartz.impl.calendar包下提供了若干个Calendar的实现类,如AnnualCalendar、MonthlyCalendar、WeeklyCalendar分别针对每年、每月和每周进行定义;
Scheduler可以将Trigger绑定到某一JobDetail中, 这样当Trigger触发时, 对应的Job就被执行。一个Job可以对应多个Trigger, 但一个Trigger只能对应一个Job。可以通过SchedulerFactory创建一个Scheduler实例。Scheduler拥有一个SchedulerContext,它类似于ServletContext,保存着Scheduler上下文信息,Job和Trigger都可以访问SchedulerContext内的信息。SchedulerContext内部通过一个Map,以键值对的方式维护这些上下文数据,SchedulerContext为保存和获取数据提供了多个put()和getXxx()的方法。可以通过Scheduler# getContext()获取对应的SchedulerContext实例;
Job有一个StatefulJob子接口,代表有状态的任务,该接口是一个没有方法的标签接口,其目的是让Quartz知道任务的类型,以便采用不同的执行方案。无状态任务在执行时拥有自己的JobDataMap拷贝,对JobDataMap的更改不会影响下次的执行。而有状态任务共享共享同一个JobDataMap实例,每次任务执行对JobDataMap所做的更改会保存下来,后面的执行可以看到这个更改,也即每次执行任务后都会对后面的执行发生影响。
正因为这个原因,无状态的Job可以并发执行,而有状态的StatefulJob不能并发执行,这意味着如果前次的StatefulJob还没有执行完毕,下一次的任务将阻塞等待,直到前次任务执行完毕。有状态任务比无状态任务需要考虑更多的因素,程序往往拥有更高的复杂度,因此除非必要,应该尽量使用无状态的Job。
如果Quartz使用了数据库持久化任务调度信息,无状态的JobDataMap仅会在Scheduler注册任务时保持一次,而有状态任务对应的JobDataMap在每次执行任务后都会进行保存。
Trigger自身也可以拥有一个JobDataMap,其关联的Job可以通过JobExecutionContext#getTrigger().getJobDataMap()获取Trigger中的JobDataMap。不管是有状态还是无状态的任务,在任务执行期间对Trigger的JobDataMap所做的更改都不会进行持久,也即不会对下次的执行产生影响。
Quartz拥有完善的事件和监听体系,大部分组件都拥有事件,如任务执行前事件、任务执行后事件、触发器触发前事件、触发后事件、调度器开始事件、关闭事件等等,可以注册相应的监听器处理感兴趣的事件。
下图描述了Scheduler的内部组件结构,SchedulerContext提供Scheduler全局可见的上下文信息,每一个任务都对应一个JobDataMap,虚线表达的JobDataMap表示对应有状态的任务:
2.入门程序
2.1先准备环境
<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.3</version></dependency>
2.2 HelloJob.java代码
/** * @author Merlin * @version 1.0.0 * @filename HelloJob.java * @time 2017年7月7日 下午8:14:11 * @copyright(C) 2017 */package com.merlin.quertz;import java.text.SimpleDateFormat;import java.util.Date;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;/** * Quertz入门一 * *实现每隔2秒打印一次 Hello Word * @see * @since */public class HelloJob implements Job {@Overridepublic void execute(JobExecutionContext arg0) throws JobExecutionException {//打印当前执行时间SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-HH:hh:mm:ss");Date date = new Date();System.out.println("current exec is time: "+sdf.format(date));//编写具体的业务逻辑 System.out.println("Hello Word!"); //打印Hello Word!}}
2.3 HelloScheduler.java代码
* @author Merlin * @version 1.0.0 * @filename HelloScheduler.java * @time 2017年7月7日 下午8:21:14 * @copyright(C) 2017 */package com.merlin.quertz;import java.text.SimpleDateFormat;import java.util.Date;import org.quartz.JobBuilder;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.SchedulerFactory;import org.quartz.SimpleScheduleBuilder;import org.quartz.Trigger;import org.quartz.TriggerBuilder;import org.quartz.impl.StdSchedulerFactory;/** * Quertz入门一 * * @see * @since */public class HelloScheduler {public static void main(String[] args) throws SchedulerException {// 创建一个JobDetail实例,将该实例与HelloWord Class绑定JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("myjob", "group1").build();// 创建一个Trigger实例,定义该Job立即执行,并且每隔两秒钟重复执行一次,直到永远Trigger trigger = TriggerBuilder.newTrigger().withIdentity("mytigger", "group1") // 这个group1跟上面的group1无关,属于不同的类.startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();// 创建Scheduler实例SchedulerFactory sfact = new StdSchedulerFactory();Scheduler scheduler = sfact.getScheduler();scheduler.start();// 打印当前执行时间 时间格式为:2017-07-20:08:32:41SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-HH:hh:mm:ss");Date date = new Date();System.out.println("current exec is time: " + sdf.format(date));scheduler.scheduleJob(jobDetail, trigger);// 将jobDetail 和tigger绑定在一起。}}
3.结果如下:
- Quartz 入门(1)
- quartz-2.2.x 快速入门 (1)
- quartz入门学习(二)
- Quartz入门Demo(一)
- 详细讲解Quartz如何从入门到精通 (1)
- Quartz 入门
- Quartz入门
- quartz入门
- Quartz入门
- Quartz入门
- Quartz入门
- Quartz入门
- Quartz入门
- Quartz入门
- Quartz学习——Quartz简单入门Demo(二)
- Quartz学习——Quartz简单入门Demo(二)
- Quartz入门实例1-Hello job
- Quartz 框架快速入门(四)
- C语言字符串相关操作总结
- OpenCV获取摄像头数据并显示在窗口里 Python实现
- 贪心算法 POJ3253 Fence Repair
- The MRC database dictionary之MRC_words
- SQLite与Android的数据交互
- Quartz 入门(1)
- CameraDemo
- Transaction rolled back because it has been marked as rollback-only解决方案
- 匿名组合-golang
- JAVAWEB开发之redis学习(八)——redis事务
- 字节流/输入输出
- Day20-jsp & el & jstl
- Intent隐式与显式
- 关于用深度学习做answer selection的论文