Quartz是OpenSymphony提供的强大的开源任务调度框架。
官网:www.quartz-scheduler.org
纯Java实现,精细控制排程。
java
1)任务: 数据库
Job:表示一个工做,要执行的具体内容。此接口中只有一个方法。要建立一个任务,必须得实现这个接口。该接口只有一个execute方法,任务每次被调用的时候都会执行这个execute方法的逻辑,相似TimerTask的run方法,在里面编写业务逻辑。 设计模式
public class TestJob implements Job {
/**把要执行的操做,写在execute方法中 */
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println("I can do something...");
System.out.println(sdf.format(new Date()));
}
}复制代码
生命周期:在每次调度器执行job时,它在调用execute方法前会建立一个新的job实例,当调用完成以后,关联的job对象实例会被释放,释放的实例会被垃圾回收机制回收。bash
JobBuilder:可向任务传递数据,一般状况下,咱们使用它就可向任务类发送数据了,若有特别复杂的传递参数,它提供了一个传递递:JobDataMap对象的方法 服务器
JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity("testJob","group1").build();复制代码
JobDetail:用来保存咱们任务的详细信息。一个JobDetail能够有多个Trigger,可是一个Trigger只能对应一个JobDetail。下面是JobDetail的一些经常使用的属性和含义: 并发
JobStore:负责跟踪全部你给scheduler的“工做数据”:jobs, triggers, calendars, 等。框架
RAMJobStore:是使用最简单的也是最高效(依据CPU时间)的JobStore 。RAMJobStore 正如它名字描述的同样,它保存数据在RAM。缺点是你的应用结束以后全部的数据也丢失了--这意味着RAMJobStore 不具备保持job和trigger持久的能力。对于一些程序是能够接受的,甚至是指望的,但对于其余的程序多是灾难性的。使用RAMJobStore配置Quartz:配置以下分布式
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore 复制代码
JDBCJobStore:以JDBC的方式保存数据在数据库中。它比RAMJobStore的配置复杂一点,也没有RAMJobStore快。然而,性能缺点不是糟透了,特别是若是你在数据库表主键上创建了索引。在机器之间的LAN(在scheduler 和数据库之间)合理的状况下,检索和更新一个被触发的Trigger花费的时间少于10毫秒。几乎适用于全部的数据库,普遍用于 Oracle。PostgreSQL, MySQL, MS SQLServer, HSQLDB, 和DB2。使用JDBCJobStore以前你必须首先建立一系列Quartz要使用的表。你能够发现表建立语句在Quartz发布目录的 “docs/dbTables”下面。你须要肯定你的应用要使用的事务类型。若是你不想绑定调度命令(例如增长和移除Trigger)到其余的事务,你可使用JobStoreTX (最经常使用的选择)做为你的Jobstore。若是你须要Quartz和其余的事务(例如在J2EE应用服务器中)一块儿工做,你应该使用JobStoreCMT ,Quartz 将让应用服务器容器管理这个事务。使用JobStoreTx配置Quartz:ide
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#配置表的前缀
org.quartz.jobStore.tablePrefix = QRTZ_
#使用JNDI数据源的时候,数据源的名字
org.quartz.jobStore.dataSource = myDS 复制代码
TerracottaJobStore:提供了一个方法:在不使用数据库的状况下使它具备收缩性和强壮性。能够是集群的也能够是非集群的,在这两种状况下为你的job数据提供了一个存储机制用于应用程序重启之间持久,由于数据是存储在Terracotta服务器。它的性能比使用数据库访问JDBCJobStore好一点儿(大约是一个数量级),可是明显比RAMJobStore慢。使用TerracottaJobStore配置Quartz:函数
org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore
org.quartz.jobStore.tcConfigUrl = localhost:9510 复制代码
JobDataMap:中能够包含不限量的(序列化的)数据对象,在job实例执行的时候,可使用其中的数据;JobDataMap是Java Map接口的一个实现,额外增长了一些便于存取基本类型的数据的方法。
存:
JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity("testJob","group1").usingJobData("date1","存内容").build(); 复制代码
取:
public class TestJob implements Job {
/**把要执行的操做,写在execute方法中 */
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobKey key = jobExecutionContext.getJobDetail().getKey();
JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
String date1 = jobDataMap.getString("date1");
}
}复制代码
2)触发器:用来触发执行Job
2.1)触发器通用属性:
2.2)触发器类型:
SimpleTrigger: 主要是针对一些相对简单的时间触发进行配置使用,好比在指定的时间开始而后在必定的时间间隔以内重复执行一个Job,同时能够任意指定重复的次数。下面就是使用一个SimpleTrigger的例子:
//建立触发器 每3秒钟执行一次(无开始时间和结束时间)
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group3")
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(3).repeatForever()).build();
//建立触发器 每3秒钟执行一次(有开始时间和结束时间)
long now = new Date().getTime();
Date start = new Date(now+6000);
Date end = new Date(now+12000);
//建立触发器 每3秒钟执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group3")
.startAt(start)
.endAt(end)
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).repeatForever()).build();复制代码
SimpleTrigger具备丰富的构造函数,根据业务需求构造不一样的构造函数。
CronTrigger: 能够配置更复杂的触发时刻表,基于日历的做业触发器,而不像SimpleTrigger那样精确指定间隔时间,比SimpleTrigger更加经常使用。
Cron表达式:用于配置CronTrigger实例,是由7个表达式组成的字符串,描述了时间表的详细信息。
格式为:[秒][分][时][日][月][周][年]
Cron表达式特殊字符意义对应表:
TriggerBuilder.newTrigger().withIdentity("trigger2","group2")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 9 ? * 6L *")).build();复制代码
Cron表达式小技巧:
1. ‘L’和‘W’能够一块儿组合使用
2. 周字段英文字母不区分大小写即MOM与mom相同
3. 利用工具,在线生成cron表达式:cron.qqe2.com/
NthIncludedDayTrigger:是 Quartz 开发团队最新加入到框架中的一个 Trigger。它设计用于在每一间隔类型的第几天执行 Job。例如,你要在每月的 15 号执行开票的 Job,用 NthIncludedDayTrigger就再合适不过了。
NthIncludedDayTrigger trigger = new NthIncludedDayTrigger("NthIncludedDayTrigger",Scheduler.DEFAULT_GROUP);
trigger.setN(15);
trigger.setIntervalType(NthIncludedDayTrigger.INTERVAL_TYPE_MONTHLY);复制代码
3)调度器Scheduler
表明一个Quartz的独立运行容器,Trigger和JobDetail能够注册到Scheduler中,二者在Scheduler中拥有各自的组及名称,组及名称是Scheduler查找定位容器中某一对象的依据,Trigger的组及名称必须惟一,JobDetail的组和名称也必须惟一(但能够和Trigger的组和名称相同,由于它们是不一样类型的)。Scheduler定义了多个接口方法,容许外部经过组及名称访问和控制容器中Trigger和JobDetail。
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实例;
SchedulerFactory schedulerfactory=new StdSchedulerFactory();
Scheduler scheduler = schedulerfactory.getScheduler();
DirectSchedulerFactory factory = DirectSchedulerFactory.getInstance();
try {
Scheduler scheduler = factory.getScheduler();
} catch (SchedulerException e) {
e.printStackTrace();
}复制代码
4)SchedulerFactory:
5)quartz.properties:
Quartz-Job的quartz.properties配置文件说明,此文件在quartz的jar包有,可直接拿过来使用不过只有基本的几个配置 本身可根据须要进行扩充;另外若是项目中没有对该配置文件重写,则Quartz会加载本身jar包中的quartz.properties文件。
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
# ===========================================================================
# Configure Main Scheduler Properties 调度器属性
# ===========================================================================
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
#org.quartz.scheduler.instanceid:AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
# ===========================================================================
# Configure ThreadPool 线程池属性
# ===========================================================================
#线程池的实现类(通常使用SimpleThreadPool便可知足几乎全部用户的需求)
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
#指定线程数,至少为1(无默认值)(通常设置为1-100直接的整数合适)
org.quartz.threadPool.threadCount: 10
#设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
org.quartz.threadPool.threadPriority: 5
#设置SimpleThreadPool的一些属性
#设置是否为守护线程
#org.quartz.threadpool.makethreadsdaemons = false
#org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
#org.quartz.threadpool.threadsinheritgroupofinitializingthread=false
#线程前缀默认值是:[Scheduler Name]_Worker
#org.quartz.threadpool.threadnameprefix=swhJobThead;
# 配置全局监听(TriggerListener,JobListener) 则应用程序能够接收和执行 预约的事件通知
# ===========================================================================
# Configuring a Global TriggerListener 配置全局的Trigger监听器
# MyTriggerListenerClass 类必须有一个无参数的构造函数,和 属性的set方法,目前2.2.x只支持原始数据类型的值(包括字符串)
# ===========================================================================
#org.quartz.triggerListener.NAME.class = com.swh.MyTriggerListenerClass
#org.quartz.triggerListener.NAME.propName = propValue
#org.quartz.triggerListener.NAME.prop2Name = prop2Value
# ===========================================================================
# Configuring a Global JobListener 配置全局的Job监听器
# MyJobListenerClass 类必须有一个无参数的构造函数,和 属性的set方法,目前2.2.x只支持原始数据类型的值(包括字符串)
# ===========================================================================
#org.quartz.jobListener.NAME.class = com.swh.MyJobListenerClass
#org.quartz.jobListener.NAME.propName = propValue
#org.quartz.jobListener.NAME.prop2Name = prop2Value
# ===========================================================================
# Configure JobStore 存储调度信息(工做,触发器和日历等)
# ===========================================================================
# 信息保存时间 默认值60秒
org.quartz.jobStore.misfireThreshold: 60000
#保存job和Trigger的状态信息到内存中的类
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
# ===========================================================================
# Configure SchedulerPlugins 插件属性 配置
# ===========================================================================
# 自定义插件
#org.quartz.plugin.NAME.class = com.swh.MyPluginClass
#org.quartz.plugin.NAME.propName = propValue
#org.quartz.plugin.NAME.prop2Name = prop2Value
#配置trigger执行历史日志(能够看到类的文档和参数列表)
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin
org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger {1}.{0} fired job {6}.{5} at: {4, date, HH:mm:ss MM/dd/yyyy}
org.quartz.plugin.triggHistory.triggerCompleteMessage = Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH:mm:ss MM/dd/yyyy} with resulting trigger instruction code: {9}
#配置job调度插件 quartz_jobs(jobs and triggers内容)的XML文档
#加载 Job 和 Trigger 信息的类 (1.8以前用:org.quartz.plugins.xml.JobInitializationPlugin)
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
#指定存放调度器(Job 和 Trigger)信息的xml文件,默认是classpath下quartz_jobs.xml
org.quartz.plugin.jobInitializer.fileNames = my_quartz_job2.xml
#org.quartz.plugin.jobInitializer.overWriteExistingJobs = false
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
#自动扫描任务单并发现改动的时间间隔,单位为秒
org.quartz.plugin.jobInitializer.scanInterval = 10
#覆盖任务调度器中同名的jobDetail,避免只修改了CronExpression所形成的不能从新生效状况
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
# ===========================================================================
# Sample configuration of ShutdownHookPlugin ShutdownHookPlugin插件的配置样例
# ===========================================================================
#org.quartz.plugin.shutdownhook.class = \org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownhook.cleanShutdown = true
#
# Configure RMI Settings 远程服务调用配置
#
#若是你想quartz-scheduler出口自己经过RMI做为服务器,而后设置“出口”标志true(默认值为false)。
#org.quartz.scheduler.rmi.export = false
#主机上rmi注册表(默认值localhost)
#org.quartz.scheduler.rmi.registryhost = localhost
#注册监听端口号(默认值1099)
#org.quartz.scheduler.rmi.registryport = 1099
#建立rmi注册,false/never:若是你已经有一个在运行或不想进行建立注册
# true/as_needed:第一次尝试使用现有的注册,而后再回来进行建立
# always:先进行建立一个注册,而后再使用回来使用注册
#org.quartz.scheduler.rmi.createregistry = never
#Quartz Scheduler服务端端口,默认是随机分配RMI注册表
#org.quartz.scheduler.rmi.serverport = 1098
#true:连接远程服务调度(客户端),这个也要指定registryhost和registryport,默认为false
# 若是export和proxy同时指定为true,则export的设置将被忽略
#org.quartz.scheduler.rmi.proxy = false 复制代码