Quartz学习笔记
- 格式:doc
- 大小:83.00 KB
- 文档页数:5
Quartz学习--quartz基本介绍和Cron表达式表名称说明qrtz_blob_triggers Trigger作为Blob类型存储(⽤于Quartz⽤户⽤JDBC创建他们⾃⼰定制的Trigger类型,JobStore 并不知道如何存储实例的时候)qrtz_calendars以Blob类型存储Quartz的Calendar⽇历信息, quartz可配置⼀个⽇历来指定⼀个时间范围负责执⾏向QuartzScheduler注册的触发Trigger的⼯作线程ThreadPool :Scheduler使⽤⼀个线程作为任务运⾏的基础设施,任务通过共享线程池中的线程提⾼运⾏效率QuartzSchedulerResources :包含穿件QuartzScheduler实例所需的所有资源(JobStore,ThreadPool等)JobStore :通过类实现的接⼝,这些类要为org.quartz.core.QuartzScheduler的使⽤提供⼀个org.quartz.Job和org.quartz.Trigger存储机制.作业和触发器的存储应该以其名称和组的组合为唯⼀性QuartzScheduler :Quartz的核⼼,他是org.quartz.Scheduler接⼝的间接实现,包含调度org.quartz.Jobs ,注册org.quartz.JobListener实例等的⽅法Scheduler :这是Quartz Scheduler的主要接⼝,代表⼀个独⽴运⾏容器. 调度程序维护JobDetails和触发器的注册表.⼀旦注册,调度程序负责执⾏作业,当她们的相关连的触发器触发(当她们的预定时间到达时 )Trigger:具有所有触发器通⽤属性的基本接⼝,描述了job执⾏的时间触发规则,使⽤TriggerBuilder实例化实际触发器JobDetail :传递给定作业实例的详细信息属性.JobDetails将使⽤JobBuilder创建/定义Job :表⽰要执⾏的"作业"的类的实现接⼝.只有⼀个⽅法:void execute(JobExecutionContext context);(JobExecutionContext 提供调度上下⽂各种信息,运⾏时数据保存在jobDataMap中 )Job 有个⼦接⼝StatefulJob,代表没有状态任务有状态任务不可并发,前次任务没有执⾏完,后⾯任务则⼀直处于阻塞等待状态2. ⼀个job可以被多个Trigger 绑定,但是⼀个Trigger只能绑定⼀个job!7. quartz.properties Quartz可更改配置//调度标识名集群中每⼀个实例都必须使⽤相同的名称(区分特定的调度器实例)org.quartz.scheduler.instanceName:DefaultQuartzScheduler//ID设置为⾃动获取每⼀个必须不同(所有调度器实例中是唯⼀的)org.quartz.scheduler.instanceId :AUTO//数据保存⽅式为持久化org.quartz.jobStore.class :org.quartz.impl.jdbcjobstore.JobStoreTX//表的前缀org.quartz.jobStore.tablePrefix : QRTZ_//设置为TRUE不会出现序列化⾮字符串类到 BLOB 时产⽣的类版本问题//eProperties : true//加⼊集群 true 为集群 false不是集群org.quartz.jobStore.isClustered : false//调度实例失效的检查时间间隔org.quartz.jobStore.clusterCheckinInterval:20000//容许的最⼤作业延长时间org.quartz.jobStore.misfireThreshold :60000//ThreadPool 实现的类名org.quartz.threadPool.class:org.quartz.simpl.SimpleThreadPool//线程数量org.quartz.threadPool.threadCount : 10//线程优先级org.quartz.threadPool.threadPriority : 5(threadPriority 属性的最⼤值是常量 ng.Thread.MAX_PRIORITY,等于10。
原创Quartz定时任务学习(一)简单任务学习quartz首先了解三个概念:调度器:负责调度作业和触发器;触发器:设置作业执行的时间、参数、条件等;(简单触发器和Cron触发器)作业:定时任务内容,被执行的程序;下载必要的jar包,将quartz-x.x.x.jar和core和/或optional文件夹中的jar文件放在项目的文件夹或项目的类路径中Quartz的几个核心的接口和类为:Job接口:自己写的"定时程序"实现此接口的voidexecute(JobExecutionContext arg0)方法,Job还有一类为有状态的StatefulJob接口,如果我们需要在上一个作业执行完后,根据其执行结果再进行下次作业的执行,则需要实现此接口。
Trigger抽象类:调度类(Scheduler)在时间到时调用此类,再由trigger 类调用指定的定时程序。
Quertz中提供了两类触发器为:SimpleTrigger,CronTrigger。
前者用于实现比较简单的定时功能,例如几点开始,几点结束,隔多长时间执行,共执行多少次等,后者提供了使用表达式来描述定时功能,因此适用于比较复杂的定时描述,例如每个月的最后一个周五,每周的周四等。
JobDetail类:具体某个定时程序的详细描述,包括Name,Group,JobDataMap等。
JobExecutionContext类:定时程序执行的run-time的上下文环境,用于得到当前执行的Job的名字,配置的参数等。
JobDataMap类:用于描述一个作业的参数,参数可以为任何基本类型例如String,float等,也可为某个对象的引用.JobListener,TriggerListener接口:用于监听触发器状态和作业扫行状态,在特写状态执行相应操作。
JobStore类:在哪里执行定进程序,可选的有在内存中,在数据库中。
开始:边看例题边学习,首先从简单触发器开始…1、作业通过实现org.quartz.job接口,可以使Java类变成可执行的。
详细讲解Quartz如何从入门到精通(1)作者:David_w_johnson 发文时间:2005。
11.22http://tech。
ccidnet。
com/art/1112/20051122/377733_1.htmlQuartz是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE 和J2EE应用中.它提供了巨大的灵活性而不牺牲简单性。
你能够用它来为执行一个作业而创建简单的或复杂的调度。
它有很多特征,如:数据库支持,集群,插件,EJB作业预构建,JavaMail及其它,支持cron-like表达式等等。
本文内容1、Quartz让任务调度简单2、Quartz的发展史3、上手Quartz4、Quartz内部架构5、作业6、作业管理和存储7、有效作业存储8、作业和触发器9、调度一个作业10、用调度器(Scheduler)调用你的作业11、编程调度同声明性调度12、有状态和无状态作业13、Quartz框架的其他特征14、Quartz下一步计划15、了解更多Quartz特征你曾经需要应用执行一个任务吗?这个任务每天或每周星期二晚上11:30,或许仅仅每个月的最后一天执行。
一个自动执行而无须干预的任务在执行过程中如果发生一个严重错误,应用能够知到其执行失败并尝试重新执行吗?你和你的团队是用 Java编程吗?如果这些问题中任何一个你回答是,那么你应该使用Quartz调度器。
旁注:Matrix目前就大量使用到了Quartz。
比如,排名统计功能的实现,在Jmatrix里通过Quartz定义了一个定时调度作业,在每天凌晨一点,作业开始工作,重新统计大家的Karma和排名等.还有,RSS文件的生成,也是通过Quartz定义作业,每隔半个小时生成一次RSS XML文件。
所以Quartz使用的地方很多,本文无疑是一篇很好的入门和进阶的文章,在此,感谢David w Johnson的努力!Quartz让作业调度简单Quartz是一个完全由Java编写的开源作业调度框架。
详细讲解Quartz如何从入门到精通Quartz是一个开源的作业调度框架它完全由Java写成并设计用于J SE和J EE应用中它提供了巨大的灵活性而不牺牲简单性你能够用它来为执行一个作业而创建简单的或复杂的调度它有很多特征如数据库支持集群插件EJB作业预构建JavaMail及其它支持cron like 表达式等等你曾经需要应用执行一个任务吗?这个任务每天或每周星期二晚上或许仅仅每个月的最后一天执行一个自动执行而无须干预的任务在执行过程中如果发生一个严重错误应用能够知到其执行失败并尝试重新执行吗?你和你的团队是用Java编程吗?如果这些问题中任何一个你回答是那么你应该使用Quartz调度器旁注 Matrix目前就大量使用到了Quartz 比如排名统计功能的实现在Jmatrix里通过Quartz定义了一个定时调度作业在每天凌晨一点作业开始工作重新统计大家的Karma和排名等还有 RSS文件的生成也是通过Quartz定义作业每隔半个小时生成一次RSS XML文件Quartz让作业调度简单Quartz是一个完全由Java编写的开源作业调度框架不要让作业调度这个术语吓着你尽管Quartz框架整合了许多额外功能但就其简易形式看你会发现它易用得简直让人受不了!简单地创建一个实现quartz Job接口的Java类 Job接口包含唯一的方法在你的Job接口实现类里面添加一些逻辑到execute()方法一旦你配置好Job实现类并设定好调度时间表 Quartz将密切注意剩余时间当调度程序确定该是通知你的作业的时候 Quartz框架将调用你Job实现类(作业类)上的execute()方法并允许做它该做的事情无需报告任何东西给调度器或调用任何特定的东西仅仅执行任务和结束任务即可如果配置你的作业在随后再次被调用 Quartz框架将在恰当的时间再次调用它如果你使用了其它流行的开源框架象struts 你会对Quartz的设计和部件感到舒适虽然两个开源工程是解决完全不同的问题还是有很多相似的之处就是开源软件用户每天感觉很舒适Quartz能用在单机J SE应用中作为一个RMI服务器也可以用在web应用中甚至也可以用在J EE应用服务器中Quartz的发展史尽管Quartz今年开始受到人们注意但还是暂时流行Quartz由James House创建并最初于年春天被加入sourcefe工程接下来的几年里有许多新特征和版本出现但是直到项目迁移到新的站点并成为OpenSymphony项目家族的一员才开始真正启动并受到应有的关注James House仍然和几个协助他的业余开发者参与大量开发工作Quartz开发团队今年能发布几个新版本包括当前正处在候选发布阶段的版上手QuartzQuartz工程驻留在OpenSymphony站点上在Quartz站点上可以找到许多有用的资源 JavaDocs 包含指南的文档 CVS访问用户和开发者论坛的连接当然也有下载从下载连接取得Quartz的发布版本并且解压到到本地目录这个下载文件包含了一个预先构建好的Quartz二进制文件(quartz jar)你可以将它放进自己的应用中Quartz框架只需要少数的第三方库并且这些三方库是必需的你很可能已经在使用这些库了你要把Quartz的安装目录的/lib/core 和 /lib/optional目录中的第三方库加进你自己的工程中大多数第三方库是我们所熟知和喜欢的标准Jakarta Commons库像Commons Logging Commons BeantUtils等等quartz properties文件Quartz有一个叫做quartz properties的配置文件它允许你修改框架运行时环境缺省是使用Quartz jar里面的quartz properties文件当然你应该创建一个quartz properties文件的副本并且把它放入你工程的classes目录中以便类装载器找到它一旦将Quartz jar文件和第三方库加到自己的工程里面并且quartz properties文件在工程的classes目录中就可以创建作业了然而在做这之前我们暂且回避一下先简短讨论一下Quartz架构Quartz内部架构在规模方面 Quartz跟大多数开源框架类似大约有个Java类和接口并被组织到个包中这可以和Apache Struts把大约个类和接口以及组织到个包中相比尽管规模几乎不会用来作为衡量框架质量的一个特性但这里的关键是quarts内含很多功能这些功能和特性集是否成为或者应该成为评判一个开源或非开源框架质量的因素Quartz调度器Quartz框架的核心是调度器调度器负责管理Quartz应用运行时环境调度器不是靠自己做所有的工作而是依赖框架内一些非常重要的部件 Quartz不仅仅是线程和线程管理为确保可伸缩性 Quartz采用了基于多线程的架构启动时框架初始化一套worker线程这套线程被调度器用来执行预定的作业这就是Quartz怎样能并发运行多个作业的原理 Quartz依赖一套松耦合的线程池管理部件来管理线程环境本文中我们会多次提到线程池管理但Quartz里面的每个对象是可配置的或者是可定制的所以例如如果你想要 *** 自己线程池管理设施我猜你一定能!作业用Quartz的行话讲作业是一个执行任务的简单Java类任务可以是任何Java代码只需你实现 quartz Job接口并且在出现严重错误情况下抛出JobExecutionException异常即可Job接口包含唯一的一个方法execute() 作业从这里开始执行一旦实现了Job接口和execute()方法当Quartz确定该是作业运行的时候它将调用你的作业Execute()方法内就完全是你要做的事情下面有一些你要在作业里面做事情的例子· 用JavaMail(或者用其他的像Commons Net一样的邮件框架)发送邮件· 创建远程接口并且调用在EJB上的方法· 获取Hibernate Session 查询和更新关系数据库里的数据· 使用OSWorkflow并且从作业调用一个工作流· 使用FTP和到处移动文件· 调用Ant构建脚本开始预定构建这种可能性是无穷的正事这种无限可能性使得框架功能如此强大Quartz给你提供了一个机制来建立具有不同粒度的可重复的调度表于是你只需创建一个Java类这个类被调用而执行任务作业管理和存储作业一旦被调度调度器需要记住并且跟踪作业和它们的执行次数如果你的作业是分钟后或每秒调用这不是很有用事实上作业执行需要非常准确和即时调用在被调度作业上的execute()方法Quartz通过一个称之为作业存储(JobStore)的概念来做作业存储和管理有效作业存储Quartz提供两种基本作业存储类型第一种类型叫做RAMJobStore 它利用通常的内存来持久化调度程序信息这种作业存储类型最容易配置构造和运行对许多应用来说这种作业存储已经足够了然而因为调度程序信息是存储在被分配给JVM的内存里面所以当应用程序停止运行时所有调度信息将被丢失如果你需要在重新启动之间持久化调度信息则将需要第二种类型的作业存储第二种类型的作业存储实际上提供两种不同的实现但两种实现一般都称为JDBC作业存储两种JDBC作业存储都需要JDBC驱动程序和后台数据库来持久化调度程序信息这两种类型的不同在于你是否想要控制数据库事务或这释放控制给应用服务器例如BEA s WebLogic 或Jboss (这类似于J EE领域中Bean管理的事务和和容器管理事务之间的区别)这两种JDBC作业存储是· JobStoreTX 当你想要控制事务或工作在非应用服务器环境中是使用· JobStoreCMT 当你工作在应用服务器环境中和想要容器控制事务时使用JDBC作业存储为需要调度程序维护调度信息的用户而设计作业和触发器Quartz设计者做了一个设计选择来从调度分离开作业Quartz中的触发器用来告诉调度程序作业什么时候触发框架提供了一把触发器类型但两个最常用的是SimpleTrigger和CronTrigger SimpleTrigger 为需要简单打火调度而设计典型地如果你需要在给定的时间和重复次数或者两次打火之间等待的秒数打火一个作业那么SimpleTrigger适合你另一方面如果你有许多复杂的作业调度那么或许需要CronTriggerCronTrigger是基于Calendar like调度的当你需要在除星期六和星期天外的每天上午点半执行作业时那么应该使用CronTrigger 正如它的名字所暗示的那样 CronTrigger是基于Unix克隆表达式的作为一个例子下面的Quartz克隆表达式将在星期一到星期五的每天上午点分执行一个作业* MON FRI下面的表达式* L将在年到年的每个月的最后一个星期五上午点分执行作业你不可能用SimpleTrigger来做这些事情你可以用两者之中的任何一个但哪个跟合适则取决于你的调度需要调度一个作业让我们通过看一个例子来进入实际讨论现假定你管理一个部门无论何时候客户在它的FTP服务器上存储一个文件都得用电子邮件通知它我们的作业将用FTP登陆到远程服务器并下载所有找到的文件然后它将发送一封含有找到和下载的文件数量的电子邮件这个作业很容易就帮助人们整天从手工执行这个任务中解脱出来甚至连晚上都无须考虑我们可以设置作业循环不断地每秒检查一次而且工作在× 模式下这就是Quartz框架完全的用途首先创建一个Job类将执行FTP和Email逻辑下例展示了Quartz 的Job类它实现了 quartz Job接口我们故意让ScanFTPSiteJob保持很简单我们为这个例子创建了一个叫做JobUtil的实用类它不是Quartz的组成部分但对构建各种作业能重用的实用程序库来说是有意义的我们可以轻易将那种代码组织进作业类中 quarts 调度器一样好用因为我们一直在使用quarts 所以那些代码可继续重用JobUtil checkForFiles() and JobUtil sendEmail()方法使用的参数是Quartz创建的JobDataMap的实例实例为每个作业的执行而创建它是向作业类传递配置参数的方法这里并没有展示JobUtil的实现但我们能用Jakarta上的Commons Net轻易地实现FTP和Email功能用调度器调用作业首先创建一个作业但为使作业能被调度器调用你得向调度程序说明你的作业的调用时间和频率这个事情由与作业相关的触发器来完成因为我们仅仅对大约每秒循环调用作业感兴趣所以打算使用SimpleTrigger作业和触发器通过Quartz调度器接口而被调度我们需要从调度器工厂类取得一个调度器的实例最容易的办法是调用StdSchedulerFactory这个类上的静态方法getDefaultScheduler() 使用Quartz框架你需要调用start()方法来启动调度器例的代码遵循了大多数Quartz应用的一般模式创建一个或多个作业创建和设置触发器用调度器调度作业和触发器启动调度器编程调度同声明性调度我们通过编程的方法调度我们的ScanFTPSiteJob作业就是说我们用Java代码来设置作业和触发器Quartz框架也支持在xml文件里面申明性的设置作业调度申明性方法允许我们更快速地修改哪个作业什么时候被执行Quartz框架有一个插件这个插件负责读取xml配置文件xml配置文件包含了关于启动Quartz应用的作业和触发器信息所有xml文件中的作业连同相关的触发器都被加进调度器你仍然需要编写作业类但配置那些作业类的调度器则非常动态化你可以将xml文件中的元素跟例代码作个比较它们从概念上来看是相同的使用申明性方法的好处是维护变得极其简单只需改变xml配置文件和重新启动Quartz应用即可无须修改代码无须重新编译无须重新部署有状态和无状态作业在本文中你所看到的作业到是无状态的这意味着在两次作业执行之间不会去维护作业执行时JobDataMap的状态改变如果你需要能增删改JobDataMap的值而且能让作业在下次执行时能看到这个状态改变则需要用Quartz有状态作业如果你是一个有经验的EJB开发者的话深信你会立即退缩因为有状态带有负面含义这主要是由于EJB带来的伸缩性问题Quartz有状态作业实现了 quartz StatefulJob接口无状态和有状态作业的关键不同是有状态作业在每次执行时只有一个实例大多数情况下有状态的作业不回带来大的问题然而如果你有一个需要频繁执行的作业或者需要很长时间才能完成的作业那么有状态作业可能给你带来伸缩性问题Quartz框架的其他特征Quartz框架有一个丰富的特征集事实上quarts有太多特性以致不能在一种情况中全部领会下面列出了一些有意思的特征但没时间在此详细讨论监听器和插件每个人都喜欢监听和插件今天几乎下载任何开源框架你必定会发现支持这两个概念监听是你创建的Java类当关键事件发生时会收到框架的回调例如当一个作业被调度没有调度或触发器终止和不再打火时这些都可以通过设置来来通知你的监听器Quartz框架包含了调度器监听作业和触发器监听你可以配置作业和触发器监听为全局监听或者是特定于作业和触发器的监听一旦你的一个具体监听被调用你就能使用这个技术来做一些你想要在监听类里面做的事情例如你如果想要在每次作业完成时发送一个电子邮件你可以将这个逻辑写进作业里面也可以JobListener里面写进JobListener的方式强制使用松耦合有利于设计上做到更好Quartz插件是一个新的功能特性无须修改Quartz源码便可被创建和添加进Quartz框架他为想要扩展Quartz框架又没有时间提交改变给Quartz开发团队和等待新版本的开发人员而设计如果你熟悉Struts插件的话那么完全可以理解Quartz插件的使用与其Quartz提供一个不能满足你需要的有限扩展点还不如通过使用插件来拥有可修整的扩展点集群Quartz应用Quartz应用能被集群是水平集群还是垂直集群取决于你自己的需要集群提供以下好处· 伸缩性· 搞可用性· 负载均衡目前Quartz只能借助关系数据库和JDBC作业存储支持集群将来的版本这个制约将消失并且用RAMJobStore集群将是可能的而且将不需要数据库的支持Quartz web应用使用框架几个星期或几个月后 Quartz用户所显示的需求之一是需要集成Quartz到图形用户界面中目前Quartz框架已经有一些工具允许你使用Java servlet来初始化和启动Quartz 一旦你可以访问调度器实例你就可以把它存储在web容器的servlet上下文中(ServletContext中)并且可以通过调度器接口管理调度环境幸运的是一些开发者已正影响着单机Quartz web应用它用来更好地管理调度器环境构建在若干个流行开源框架如Struts和Spring 之上的图形用户界面支持很多功能这些功能都被包装进一个简单接口Quartz的下一步计划Quartz是一个活动中的工程Quartz开发团队明确表示不会停留在已有的荣誉上Quartz下一个主要版本已经在启动中你可以在OpenSymphony的wiki上体验一下Quartz 的设计和特征总之Quartz用户每天都自由地添加特性建议和设计创意以便能被核心框架考虑(看重)了解更多Quartz特征lishixinzhi/Article/program/Java/ky/201311/27892。
Quartz核心概念:调度器、触发器、作业[谁什么时候干什么活]任务调度Quartz(!)为何需要任务调度?在web应用中,大多数任务是以一种"防止用户长时间等待"的方式完成的。
在Google搜索这样的例子中,减少等待时间对用户体验来说至关重要。
异步任务的一种解决方案是在用户提交后生成一个线程(来处理异步任务),但这也不能解决那些需要以一定时间间隔重复运行任务、或在每天的指定时间运行任务的情况。
让我们从一个数据库报表的例子来看看任务调度能如何帮助改善系统设计。
报表可能是错综复杂的,这取决于用户所需数据的种类,以及是否需要从一个或多个数据库收集大量数据。
用户可能需要很长时间来运行这样的"按需"报表。
因此,我们向这个报表示例中添加任务调度机制,以便用户可以安排在任何他们需要的时间生成报表,并以PDF或其他格式在email中发送。
用户可以让报表在每天的凌晨2:22,系统正处于低负荷时运行;也可以选择只在特定时间运行一次。
通过在报表应用中加入任务调度,我们可以为产品添加一项有用的功能,并改善用户体验。
幸运的是,有一个强大的开源解决方案可以让我们以标准的方式在web应用(或任何Java应用)中实施任务调度。
以下示例展示了在web应用中,如何使用Quartz来创建一个任务调度框架。
这个示例还使用了Struts Action framework 插件,以便在web应用启动时初始化任务调度机制。
Struts是最常见的MVC框架,为大多数开发人员所熟悉。
当然除此之外还有许多框架可以协助在web应用中实现MVC模式。
启动时初始化任务调度器我们首先要做的是建立一个Struts插件,让它在容器启动时创建我们的任务调度器。
在以下例子中,我们选择Tomcat作为web应用容器,不过这些示例在其他容器中也应当可以运行。
我们要创建一个Struts插件类,并在struts-config.xml中加入几行代码以使之可以工作。
Quartz的基本使⽤之⼊门(2.3.0版本)⼀、Quartz可以⽤来做什么Quartz是⼀个强⼤任务调度框架,我⼯作时候会在这些情况下使⽤到quartz框架,当然还有很多的应⽤场景,在这⾥只列举2个实际⽤到的餐厅系统会在每周四晚上的22点⾃动审核并⽣成报表⼈事系统会在每天早晨8点给有待办的⼈员⾃动发送Email提醒⼆、使⽤Quartz之前的准备1.建⽴⼀个Maven项⽬2.引⼊quartz的依赖 但然也可以使⽤这个2.3.0的依赖,下⾯的例⼦都是使⽤此依赖并实现了效果。
<!-- https:///artifact/org.quartz-scheduler/quartz --><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version></dependency>三、编写第⼀个Quartz任务案例 - 每隔2秒钟打印⼀次HelloQuartz先实现⼀下这个基本的Quartz的任务再来介绍⼀下Quartz的3个重要组成,JobDetail,Trigger,Scheduler1.创建⼀个类 HelloJob.java,这个类是编写我们的具体要实现任务(打印Hello Quartz)import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import java.text.SimpleDateFormat;import java.util.Date;public class HelloJob implements Job{ public void execute(JobExecutionContext jobExecutionCo //打印当前的执⾏时间例如 2017-11-23 00:00:00Date date = new Date();SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("现在的时间是:"+ sf.format(date));//具体的业务逻辑System.out.println("Hello Quartz");}}2.创建⼀个类HelloScheduler.java,这个是具体触发我们的任务public class HelloScheduler {public static void main(String[] args) throws SchedulerException {//创建⼀个jobDetail的实例,将该实例与HelloJob Class绑定JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("myJob").build();//创建⼀个Trigger触发器的实例,定义该job⽴即执⾏,并且每2秒执⾏⼀次,⼀直执⾏SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();//创建schedule实例StdSchedulerFactory factory = new StdSchedulerFactory();Scheduler scheduler = factory.getScheduler();scheduler.start();scheduler.scheduleJob(jobDetail,trigger);}}3.执⾏main⽅法,Run 'HelloScheduler.main()',可以看见如下效果,表明任务执⾏成功了4.⼀句话看懂quartz1、创建调度⼯⼚(); //⼯⼚模式2、根据⼯⼚取得调度器实例(); //⼯⼚模式3、Builder模式构建⼦组件<Job,Trigger> // builder模式, 如JobBuilder、TriggerBuilder、DateBuilder4、通过调度器组装⼦组件调度器.组装<⼦组件1,⼦组件2...> //⼯⼚模式5、调度器.start(); //⼯⼚模式四、第⼆个案例 - 每⽇的9点40分触发任务打印HelloQuartz先上代码,然后介绍⼀下cron表达式⽣成规则。
1、 Quartz 提供强大的任务调度机制。
2、 任务调度机制包含三部分:(1) 调度器(Scheduler )(2) 任务(JobDetail )(3) 触发器(Trigger )3、 调度机制原理:(1) 实现 public class SimpleJob implements Job {public void execute(JobExecutionContext jobCtx)throws JobExecutionException {System.out.println(jobCtx.getTrigger().getName()+ " triggered. time is:" + (new Date()));}}(2) 包装JobDetail jobDetail = new JobDetail("job1_1","jGroup1", SimpleJob.class );JobDetail Job 实现类 Job 接口 包装 实现任务SimpleTrigger: 当仅需触 发一次或者以固定时间间隔周期执行;CronTrigger: 可以通过Cron 表达式定义出各种复杂时间规则的调度方案;SimpleTrigger(String name, String group):通过该构造函数指定Trigger 所属组和名称;SimpleTrigger(String name, String group, Date startTime):除指定Trigger 所属组和名称外,还可以指定触发的开发时间;SimpleTrigger(String name, String group, Date startTime, Date endTime, int repeatCount, long repeatInterval):除指定以上信息外,还可以指定结束时间、重复执行次数、时间间隔等参数;SimpleTrigger(String name, String group, String jobName, String jobGroup, Date startTime, Date endTime, int repeatCount, long repeatInterval):这是最复杂的一个构造函数,在指定触发参数的同时,还通过jobGroup 和jobName ,让该Trigger 和 Scheduler 中的某个任务关联起来。
Quartz学习介绍QuartzQuartz是一个开源的任务调度系统,它能用来调度很多任务的执行。
运行环境Quartz 能嵌入在其他应用程序里运行。
Quartz 能在一个应用服务器里被实例化(或servlet容器), 并且参与XA事务Quartz能独立运行(通过JVM),或者通过RMIQuartz能被集群实例化任务调度当一个指定给任务的触发器发生时,任务就被调度执行. 触发器能被创建为:一天的某个时间(精确到毫秒级)一周的某些天一个月的某些天一年的某些天不在一个Calendar列出的某些天 (例如工作节假日)在一个指定的次数重复重复到一个指定的时间/日期无限重复在一个间隔内重复能够给任务指定名称和组名.触发器也能够指定名称和组名,这样可以很好的在调度器里组织起来.一个加入到调度器里的任务可以被多个触发器注册。
在J2EE环境里,任务能作为一个分布式(XA)事务的一部分来执行。
任务执行任务能够是任何实现Job接口的Java类。
任务类能够被Quartz实例化,或者被你的应用框架。
当一个触发器触发时,调度器会通知实例化了JobListener 和TriggerListener 接口的0个或者多个Java对象(监听器可以是简单的Java对象, EJBs, 或JMS发布者等). 在任务执行后,这些监听器也会被通知。
当任务完成时,他们会返回一个JobCompletionCode ,这个代码告诉调度器任务执行成功或者失败.这个代码也会指示调度器做一些动作-例如立即再次执行任务。
任务持久化Quartz的设计包含JobStore接口,这个接口能被实现来为任务的存储提供不同的机制。
应用JDBCJobStore, 所有被配置成“稳定”的任务和触发器能通过JDBC存储在关系数据库里。
应用RAMJobStore, 所有任务和触发器能被存储在RAM里因此不必在程序重起之间保存-一个好处就是不必使用数据库。
事务使用JobStoreCMT(JDBCJobStore的子类),Quartz 能参与JTA事务。
作业调度框架Quartz 学习笔记(二)简单回顾一下上一节学习到的"HelloWorld "1 创建一个job类,实现Job接口,覆盖public void execute(JobExecutionContext context) 方法,在方法中写入你要执行的操作(数据导入/备份,轮询检查文件等)代码2 创建一个主线程类, 获得Scheduler 对象SchedulerFactory sf = new StdSchedulerFactory();Scheduler sched = sf.getScheduler();获得要执行的对象JobDetail job =newJob(HelloJob.class).withIdentity("job1", "group1").build();定义触发器Trigger trigger =newTrigger().withIdentity("trigger1","group1").startAt(runTime).build();将任务和Trigger放入scheduler :sched.scheduleJob(job, trigger);启动和停止sched.start(); sched.shutdown(true);注意给job 留有足够长的时间,如果主线程类停止工作,job线程也会停止工作------------------------------------------------我是分割线--------------------------------------------------------经过了"HelloWorld" 之后,您老人家可能对Quartz 有所了解,下面让我们继续深入,学习下Quartz 重复执行任务该怎么做简单的说就是触发器(Trigger)的参数设置. 什么? 触发器(Trigger)不知道是什么?出门左转<<作业调度框架Quartz 学习笔记(一)>> 不谢还是老套路,一个job 类,一个主线程类SimpleJob.java[java] view plaincopypublic class SimpleJob implements Job { @Override public voidexecute(JobExecutionContext context) throws JobExecutionException { // job 的名字String jobName = context.getJobDetail().getKey().getName(); // 任务执行的时间SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy 年MM 月dd 日HH 时mm 分ss 秒"); String jobRunTime = dateFormat.format(Calendar.getInstance().getTime());// 输出任务执行情况System.out.println("任务: "+ jobName + " 在" +jobRunTime + " 执行了"); } }在这里对输出的日期进行了一小下格式化,适应国人习惯.其它没什么好说的0.0SimpleTriggerExample.java[java] view plaincopyimport staticorg.quartz.DateBuilder.futureDate; import staticorg.quartz.JobBuilder.newJob; import staticorg.quartz.JobKey.jobKey; import staticorg.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger; importjava.text.SimpleDateFormat; import java.util.Date; import org.quartz.DateBuilder; importorg.quartz.DateBuilder.IntervalUnit; importorg.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerFactory; importorg.quartz.SchedulerMetaData; importorg.quartz.SimpleTrigger; importorg.quartz.impl.StdSchedulerFactory; /** * Simple Triggers (简单触发器) 的使用. */ public classSimpleTriggerExample { public static voidmain(String[] args) throws Exception{ SimpleTriggerExample example = new SimpleTriggerExample(); example.run(); } public void run() throws Exception { // 日期格式化SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy 年MM 月dd 日HH 时mm 分ss 秒"); SchedulerFactory sf = new StdSchedulerFactory();Scheduler sched = sf.getScheduler();System.out.println("--------------- 初始化-------------------");// 下一个第15秒例: // 当前10秒,则执行时间为15秒// 当前16秒,则执行时间为30秒// 当前33秒,则执行时间为45秒// 当前48秒,则执行时间为00秒Date startTime =DateBuilder.nextGivenSecondDate(null, 15); // job1 将只会执行一次JobDetail job =newJob(SimpleJob.class).withIdentity("job1", "group1").build(); SimpleTrigger trigger = (SimpleTrigger)newTrigger() .withIdentity("trigger1", "group1") .startAt(startTime).build();// 把job1 和trigger加入计划. ft:此任务要执行的时间Date ft = sched.scheduleJob(job, trigger);System.out.println(job.getKey().getName() + " 将在: " + dateFormat.format(ft) + " 时运行.并且重复: "+ trigger.getRepeatCount() + " 次, 每次间隔"+ trigger.getRepeatInterval() / 1000 + " 秒"); // job2 将只会和执行一次(和job1一样一样的,吼~~)job = newJob(SimpleJob.class).withIdentity("job2","group1").build(); trigger = (SimpleTrigger) newTrigger() .withIdentity("trigger2", "group1").startAt(startTime).build(); ft =sched.scheduleJob(job, trigger);System.out.println(job.getKey().getName() + " 将在: " + dateFormat.format(ft) + " 时运行.并且重复: "+ trigger.getRepeatCount() + " 次, 每次间隔"+ trigger.getRepeatInterval() / 1000 + " 秒"); // job3 将执行11次(执行1次,重复10次) ,每10秒重复一次job = newJob(SimpleJob.class).withIdentity("job3","group1").build(); trigger =newTrigger() .withIdentity("trigger3", "group1") .startAt(startTime).withSchedule( simpleS chedule() .withIntervalInSeconds(10)// 重复间隔.withRepeatCount(10))// 重复次数.build();ft = sched.scheduleJob(job, trigger);System.out.println(job.getKey().getName()+ " 将在: " + dateFormat.format(ft) + " 时运行.并且重复: "+ trigger.getRepeatCount() + " 次, 每次间隔"+ trigger.getRepeatInterval() / 1000 + " 秒");// trigger3 改变了. 每隔10s重复.共重复2次// 此处说明, 上面job3已经设定了trigger3 重复10次,每次10s // 在这里又改变了trigger3的设置,不会对以前构成影响,而是当做一个新的来处理trigger =newTrigger() .withIdentity("trigger3", "group2") .startAt(startTime).withSchedule( simpleS chedule() .withIntervalInSecond s(10) .withRepeatCount(2)).forJob(job).build(); ft = sched.scheduleJob(trigger);System.out.println(job.getKey().getName() + " 改变过trigger3属性的job3 : " + dateFormat.format(ft) + " 时运行.并且重复:" + trigger.getRepeatCount() + " 次, 每次间隔" + trigger.getRepeatInterval() / 1000 + " 秒"); // job5 将在5分钟后运行一次job = newJob(SimpleJob.class).withIdentity("job5","group1").build(); trigger = (SimpleTrigger) newTrigger() .withIdentity("trigger5", "group1") .startAt(futureDate(5, IntervalUnit.MINUTE)) // 设定5分钟后运行.build(); ft =sched.scheduleJob(job, trigger);System.out.println(job.getKey().getName()+ " 将在: " + dateFormat.format(ft) + " 时运行.并且重复: "+ trigger.getRepeatCount() + " 次, 每次间隔"+ trigger.getRepeatInterval() / 1000 + " 秒"); // job6 每40s运行一次,没有指定重复次数,则无下限的重复job = newJob(SimpleJob.class).withIdentity("job6","group1").build(); trigger =newTrigger() .withIdentity("trigger6", "group1") .startAt(startTime).withSchedule( simpleS chedule().withIntervalInSeconds(40).repeatForever()).build(); ft =sched.scheduleJob(job, trigger);System.out.println(job.getKey().getName() + " 将在: " + dateFormat.format(ft) + " 时运行.并且重复: "+ trigger.getRepeatCount() + " 次, 每次间隔"+ trigger.getRepeatInterval() / 1000 + " 秒"); // 所有的任务都被加入到了scheduler中,但只有schedulers.start(); 时才开始执行sched.start(); System.out.println("------- 开始调度(调用.start()方法)----------------"); System.out.println("-------系统启动的时间:" + dateFormat.format(new Date()));// 在scheduled.start(); 之后,还可以将jobs 添加到执行计划中// job7 将重复20次,每5分钟重复一次job = newJob(SimpleJob.class).withIdentity("job7","group1").build(); trigger =newTrigger() .withIdentity("trigger7", "group1") .startAt(startTime).withSchedule( simpleS chedule() .withIntervalInMinute s(5) // 5分钟.withRepeatCount(20))// 重复20次.build();ft = sched.scheduleJob(job, trigger);System.out.println(job.getKey().getName() + " 将在: " + dateFormat.format(ft) + " 时运行.并且重复: "+ trigger.getRepeatCount() + " 次, 每次间隔"+ trigger.getRepeatInterval() / 1000 + " 秒"); // job8 可以立即执行. 无trigger注册job = newJob(SimpleJob.class).withIdentity("job8","group1") .storeDurably().build(); sched.addJob(job, true); System.out.println("手动触发job8...(立即执行)");sched.triggerJob(jobKey("job8", "group1"));System.out.println("------- 等待30 秒... --------------");try { Thread.sleep(30L * 1000L); } catch (Exception e) { } // job7 将马上执行,重复10次,每秒一次System.out.println("------- 重新安排... --------------------"); trigger =newTrigger() .withIdentity("trigger7", "group1") .startAt(startTime).withSchedule( simpleS chedule().withIntervalInMinutes(5).withRepeatCount(20)).build(); ft = sched.rescheduleJob(trigger.getKey(), trigger);System.out.println("job7 被重新安排在: " +dateFormat.format(ft) +" 执行. \r 当前时间:" + dateFormat.format(new Date())+"预定执行时间已过,任务立即执行"); try{ System.out.println("------- 等待5分钟... ------------"); Thread.sleep(300L *1000L); } catch (Exception e) { }sched.shutdown(true); System.out.println("------- 调度已关闭---------------------"); // 显示一下已经执行的任务信息SchedulerMetaData metaData = sched.getMetaData();System.out.println("~~~~~~~~~~ 执行了" +metaData.getNumberOfJobsExecuted() + " 个jobs."); } }几点说明:1 DateBuilder.nextGivenSecondDate 的意思代码中已经说明了,就是下一个你想要的时间,不懂的可以自己测试一下2 同一个任务可以多次注册.3 重复执行需要设置trigger = newTrigger().withIdentity("trigger3", "group1").startAt(startTime).withSchedule(simpleSchedule().withIntervalInSeconds(10)// 重复间隔.withRepeatCount(10)) // 重复次数.build();如果需要一直重复:trigger = newTrigger().withIdentity("trigger6", "group1").startAt(startTime).withSchedule(simpleSchedule().withIntervalInSeconds(40).repeatForever()).build();4 无trigger注册,表示任务立即执行: sched.addJob(job, true);5 // 在scheduler.start之后调用,可以在job开始后重新定义trigger,然后重新注册sched.rescheduleJob(trigger.getKey(), trigger);这个Example 还是比较简单的,主要就是Trigger的参数设置,多看看代码,里面有注释的0.0自己动手试试吧。
quartz记单词技巧
Quartz记单词技巧主要包括以下几点:
1.制定学习计划:为了有效记忆单词,需要在合适的时间安排专门的学习时间。
制定每天学习的时间表,并保持每天的学习持续性。
3.多练习:通过反复学习和练习,加深对单词的记忆。
可以使用各种练习方式,如填空、选择、造句等等。
同时,也可以通过使用单词卡片、单词本等工具进行复习。
4.上下文记忆:学习单词时,把单词放入具体的上下文中记忆,理解单词的词义和用法。
这样可以帮助记忆,并使学习更加实际。
5.创造语境:尝试在日常生活中主动运用单词,例如在对话中使用,写文章时使用等等。
通过实际运用,加深对单词的记忆。
6.复习策略:定期进行单词复习,巩固记忆。
可以选择每周或者每月复习一次已学单词,以防止遗忘。
7.多听多读多写:通过听力、阅读和写作的实践,帮助记忆单词并提高语感,可以更好地理解单词的含义和用法。
总之,记单词需要长期坚持和不断练习,使用合适的记忆法和技巧,加入实践和上下文记忆,才能更好地记住单词。
Quartz学习笔记:集群部署⾼可⽤ 同⼀集群下,instanceName必须相同,instanceId可⾃动⽣成,isClustered为true,持久化存储,指定数据库类型对应的驱动类和数据源连接。
集群⾼可⽤数据⾏锁避免重复执⾏ Quartz究竟是如何保证集群情况下trgger处理的信息同步? 下⾯跟着源码⼀步⼀步分析,QuartzSchedulerThread包含有决定何时下⼀个Job将被触发的处理循环,主要逻辑在其run()⽅法中:public void run() {boolean lastAcquireFailed = false;while (!halted.get()) {......int availThreadCount = qsRsrcs.getThreadPool().blockForAvailableThreads();if(availThreadCount > 0) {......//调度器在trigger队列中寻找30秒内⼀定数⽬的trigger(需要保证集群节点的系统时间⼀致)triggers = qsRsrcs.getJobStore().acquireNextTriggers(now + idleWaitTime, Math.min(availThreadCount, qsRsrcs.getMaxBatchSize()), qsRsrcs.getBatchTimeWindow());......//触发triggerList<TriggerFiredResult> res = qsRsrcs.getJobStore().triggersFired(triggers);......//释放triggerfor (int i = 0; i < triggers.size(); i++) {qsRsrcs.getJobStore().releaseAcquiredTrigger(triggers.get(i));}}} 由此可知,QuartzScheduler调度线程不断获取trigger,触发trigger,释放trigger。
本文部分内容来自网络整理,本司不为其真实性负责,如有异议或侵权请及时联系,本司将立即删除!== 本文为word格式,下载后可方便编辑和修改! ==quartz配置日志篇一:Quartz学习笔记Quartz技术学习笔记Quartz特点1) Quartz能嵌入到任何独立的应用中运行。
2) Quartz能在应用服务器或者 Servlet 容器中实例化,并且能够参与 XA 事务。
3) Quartz能够以独立的方式运行(在它自己的Java虚拟机中),可以通过RMI使用 Quartz。
4) Quartz可以被实例化为独立程序的集群(有负载均衡和容错能力)。
Quartz功能介绍任务执行(Job Execution)1) 任务是任何实现简单 Job 接口的 Java 类,这样开发者能够执行任何完成他们工作的任务。
2) 任务类的实例可以由 Quartz实例化,也可以由你的程序框架实例化。
当触发器被触发时,日程管理器将会通知某个或者多个实现了JobListener 或TriggerListener的对象(监听器可以是简单的Java对象,或者 EJBs,或者JMS 消息发布器,等等)。
这些监听器在任务执行完毕后也会接到通知。
3) 任务被完成后,他们会返回一个“任务完成码(JobCompletionCode)”,这个“任务完成码”告知日程管理器任务执行的结果是成功还是失败。
日程管理器会根据成功或者失败码来采取措施,比如:立即重新执行任务任务持久化(Job Persistence)1) Quartz设计中包括了一个JobStore接口,这样,实现这个接口的 Job多种机制实现Job 的存储。
2) 存储在数据库中:通过使用 JDBCJobStore,所有的 Jobs和 Triggers 被配置为“non-volatile”(不轻快)的方式。
即,通过 JDBC 存储在关系数据库中。
3) 存储在RAM中:通过使用 RAMJobStore,所有Jobs和 Triggers 被存储在RAM。
2015年3月10日星期二1.Quartz简介Quartz是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE和J2EE应用中。
它提供了巨大的灵活性而不牺牲简单性。
你能够用它来为执行一个作业而创建简单的或复杂的调度。
它有很多特征,如:数据库支持,集群,插件,EJB作业预构建,JavaMail 及其它,支持cron-like表达式等等。
2.下载说明3.如何删除一个job1.1. 获取运行job的jobKey或者自己声明一个或者:JobKey job2_key = new JobKey("job2", "group2");1.2. 删除代码// 删除job2JobKey job2_key = new JobKey("job2", "group2");scheduler.deleteJob(job2_key);1.触发器1.2. 简单触发器1.3. Cron触发器1.1.1简介CronTrigger 支持比 SimpleTrigger 更具体的调度,而且也不是很复杂。
基于cron 表达式,CronTrigger 支持类似日历的重复间隔,而不是单一的时间间隔——这相对 SimpleTrigger 而言是一大改进。
说明:The '*' character is used to specify all values. For example, "*" in the minute field means "every minute".翻译:星号“*”代表所有的值。
例如,用在分钟字段中,代表所有“每一分”。
The '?' character is allowed for the day-of-month andday-of-week fields. It is used to specify 'no specific value'. This is useful when you need to specify something in one of the two fields, but not the other.翻译:问号’?’只能用在日和周的字段中,用来指定“没有特定的值”。
是一个开源的作业调度框架,能够应用在小到轻量级的应用程序,大到重量级的企业级系统中的全功能的开源任务调度系统。
一、特点∙API 操作简单,只要几行简单的代码你就可以在应用程序里面实现自己的作业调度,并实时监视作业执行情况。
∙触发器功能强大,比Windows 的任务计划提供更细的触发粒度,可以使用“Cron 表达式”(类似于正则表达式)。
∙良好的可扩展性,它基于接口编程,你可以实现自己的Schedule 调度器,Job 作业,以及Trigger 触发器等。
∙作业可以保存在RAM 中,也可以持久化到数据库,支持多种数据库类型:SqlSe rver、Oracle、MySql等。
∙集群,这是一个高级应用,可以在多台计算机之间创建负载平衡、容错处理。
∙支持两种途径配置应用程序的运行时属性:声明式和编程式。
二、Quartz的目录结构内容目录名存放内容Quartz.Collection 数据结构Quartz.Core 调度器,线程池Quartz.Impl 接口实现类Quartz.Job 作业Quartz. Listener 监听器Quartz. Plugin 扩展插件Quartz. Simpl 简单的调试器、线程池Quartz. SPI 接口Quartz. Util 实用方法Quartz. Xml Xml配置操作类三、作业流程的定制作业流程是在调度器的统一调度下完成的,它可以调度多个作业,触发器提供作业执行的条件(每天8:00 am),触发器与作业关联,它们是1:N 的关系。
1.JobJob每一个Quartz Job 必须有一个实现IJob接口的具体类。
这个接口仅有一个要在Job 中实现的方法,execute(),方法execute() 的原型如下:void Execute(JobExecutionContext context);可以在execute() 方法中执行你的业务逻辑:例如,也许你会调用其他构造的实例上的方法,发送一个电子邮件、FTP 传一个文件、调用一个Web 服务、执行一个工作流等。
1、Quartz 学习笔记实例Scheduler scheduler=null;try{scheduler=StdSchedulerFactory.getDefaultScheduler();scheduler.start();JobDetail jobDetail=new JobDetail("myJob",Scheduler.DEFAULT_GROUP,DumbJob.class);//Trigger trigger=new CronTrigger("myTrigger",Scheduler.DEFAULT_GROUP,"0/10 * * * * ?");//十秒钟一次Trigger trigger=new CronTrigger("myTrigger",Scheduler.DEFAULT_GROUP,"0 0/1 * * * ? *");//设置一分钟一次scheduler.scheduleJob(jobDetail,trigger);}catch(SchedulerException e){scheduler.shutdown();}Org.quartz.Job 接口为一个单独的jobOrg.quartz. TriggerUtils Trigger的创建类,也可以使用Cron字符串建立按指定时间运行的trigger。
Cron字符串分为七个字时间变量及空格分开的字符串,分别是:秒,分,时,天,月,周,年注:年可以不要设置周以SUN=1,MON,TUE,WED,THU,FRI and SAT以下是cron字符的定义用的多义字符* 代表每一个该位置的时间, 组合使用多个内容于一个字段/ 代表一个字段中以前面的为开始间隔为后面的- 为两个数据之间? 主要是用来设置天,周L 用于设置天,周#W2、Quartz 学习笔记2quartz源代码的14个例子非常好,建议分析,执行一下。
quartz由浅入深一、quartz核心概念先来看一张图:●Job:是一个接口,只有一个方法void execute(JobExecutionContext context),开发者实现该接口定义运行任务,JobExecutionContext类提供了调度上下文的各种信息。
Job运行时的信息保存在JobDataMap实例中;●JobDetail:Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。
因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。
●Trigger:是一个类,描述触发Job执行的时间触发规则。
主要有SimpleTrigger和CronTrigger这两个子类。
当仅需触发一次或者以固定时间间隔周期执行,SimpleTrigger是最适合的选择;而CronTrigger则可以通过Cron表达式定义出各种复杂时间规则的调度方案:如每早晨9:00执行,周一、周三、周五下午5:00执行等;●Calendar:org.quartz.Calendar和java.util.Calendar不同,它是一些日历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表一个日历时间点,无特殊说明后面的Calendar即指org.quartz.Calendar)。
一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点。
假设,我们安排每周星期一早上10:00执行任务,但是如果碰到法定的节日,任务则不执行,这时就需要在Trigger触发机制的基础上使用Calendar进行定点排除。
1、 Quartz 提供强大的任务调度机制。
2、 任务调度机制包含三部分:(1) 调度器(Scheduler )(2) 任务(JobDetail )(3) 触发器(Trigger )3、 调度机制原理:(1) 实现 public class SimpleJob implements Job {public void execute(JobExecutionContext jobCtx)throws JobExecutionException {System.out.println(jobCtx.getTrigger().getName()+ " triggered. time is:" + (new Date()));}}(2) 包装JobDetail jobDetail = new JobDetail("job1_1","jGroup1", SimpleJob.class );任务SimpleTrigger: 当仅需触 发一次或者以固定时间间隔周期执行;CronTrigger: 可以通过Cron 表达式定义出各种复杂时间规则的调度方案;SimpleTrigger(String name, String group):通过该构造函数指定Trigger 所属组和名称;SimpleTrigger(String name, String group, Date startTime):除指定Trigger 所属组和名称外,还可以指定触发的开发时间;SimpleTrigger(String name, String group, Date startTime, Date endTime, int repeatCount, long repeatInterval):除指定以上信息外,还可以指定结束时间、重复执行次数、时间间隔等参数;SimpleTrigger(String name, String group, String jobName, String jobGroup, Date startTime, Date endTime, int repeatCount, long repeatInterval):这是最复杂的一个构造函数,在指定触发参数的同时,还通过jobGroup 和jobName ,让该Trigger 和 Scheduler 中的某个任务关联起来。
Quartz使用手记概述这篇文章是英文教程的中文翻译,有些认为暂时使用不到的特性有省略,英文文档参见/quartz/wikidocs/TutorialLesson1.html。
如何使用使用QUARTZ调试程序之前,必须使用SchedlerFactory实例化Scheduler。
一旦实例化Scheduler后可以启动或者停止,需要注意的是一旦Scheduler关闭,必须重新实例化后才能够重启。
任务只有在Scheduler启动后才会执行。
下面的代码片断实例化并启动Scheduler,然后执行一个任务。
java 代码1. SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();2. Scheduler sched = schedFact.getScheduler();3. sched.start();4. JobDetail jobDetail = new JobDetail("myJob", null, DumbJob.class);5. Trigger trigger = TriggerUtils.makeHourlyTrigger(); // fire every hour6. trigger.setStartTime(TriggerUtils.getEvenHourDate(new Date()));7. trigger.setName("myTrigger");8. sched.scheduleJob(jobDetail, trigger);任务/触发器要定义一个任务,只需要实现Job接口即可,Job接口如下:java 代码1. package org.quartz;public interface Job { public void execute(JobExecutionContext context)2. throws JobExecutionException;3. }当任务被触发时将调用execute方法,JobExecutionContext 参数提供关于任务的运行时环境,包括一个Scheduler的引用,触发这个任务的触发器的引用,任务的JobDetail实例和一些别的信息。
1、 Quartz 提供强大的任务调度机制。
2、 任务调度机制包含三部分:(1) 调度器(Scheduler )(2) 任务(JobDetail )(3) 触发器(Trigger )3、 调度机制原理:(1) 实现 public class SimpleJob implements Job {public void execute(JobExecutionContext jobCtx)throws JobExecutionException {System.out.println(jobCtx.getTrigger().getName()+ " triggered. time is:" + (new Date()));}}(2) 包装JobDetail jobDetail = new JobDetail("job1_1","jGroup1", SimpleJob.class );任务SimpleTrigger: 当仅需触 发一次或者以固定时间间隔周期执行;CronTrigger: 可以通过Cron 表达式定义出各种复杂时间规则的调度方案;SimpleTrigger(String name, String group):通过该构造函数指定Trigger 所属组和名称;SimpleTrigger(String name, String group, Date startTime):除指定Trigger 所属组和名称外,还可以指定触发的开发时间;SimpleTrigger(String name, String group, Date startTime, Date endTime, int repeatCount, long repeatInterval):除指定以上信息外,还可以指定结束时间、重复执行次数、时间间隔等参数;SimpleTrigger(String name, String group, String jobName, String jobGroup, Date startTime, Date endTime, int repeatCount, long repeatInterval):这是最复杂的一个构造函数,在指定触发参数的同时,还通过jobGroup 和jobName ,让该Trigger 和 Scheduler 中的某个任务关联起来。
(3) 通过SimpleTrigger 定义调度规则:马上启动,每2秒运行一次,共运行100次SimpleTrigger simpleTrigger = new SimpleTrigger("trigger1_1","tgroup1");//名字和所在组 simpleTrigger.setStartTime(new Date());//设置开始时间simpleTrigger.setRepeatInterval(2000);//设置重复间隔simpleTrigger.setRepeatCount(100);//设置重复次数(4) Scheduler :代表一个Quartz 的独立运行容器,Trigger和JobDetail 可以注册到Scheduler 中,两者在 Scheduler 中拥有各自的组及名称,组及名称是Scheduler 查找定位容器中某一对象的依据//通过SchedulerFactory 获取一个调度器实例SchedulerFactory schedulerFactory = new StdSchedulerFactory();Scheduler scheduler = schedulerFactory.getScheduler();//将JobDetail 和Trigger 注册到Scheduler 中,并将Trigger 指派给JobDetail ,将两者关联起来。
scheduler.scheduleJob(jobDetail, simpleTrigger);//调度启动触发器scheduler.start();(5)另外一种关联Trigger和JobDetail的方式JobDetail jobDetail = new JobDetail("job1_1","jGroup1", SimpleJob.class);SimpleTrigger simpleTrigger = new SimpleTrigger("trigger1_1","tgroup1");…simpleTrigger.setJobGroup("jGroup1");//指定关联的Job组名simpleTrigger.setJobName("job1_1");//指定关联的Job名称scheduler.addJob(jobDetail, true);//注册JobDetailscheduler.scheduleJob(simpleTrigger);//注册指定了关联JobDetail的Trigger4、使用CronTrigger(1)Cron表达式:由6或7个由空格分隔的时间字段组成星号(*):可用在所有字段中,表示对应时间域的每一个时刻,例如,*在分钟字段时,表示“每分钟”;●问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符;●减号(-):表达一个范围,如在小时字段中使用“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表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。
(2)CronTrigger实例JobDetail jobDetail = new JobDetail("job1_2", "jGroup1",SimpleJob.class);//创建CronTrigger,指定组及名称CronTrigger cronTrigger = new CronTrigger("trigger1_2", "tgroup1"); CronExpression cexp = new CronExpression("0/5 * * * * ?");//定义Cron表达式cronTrigger.setCronExpression(cexp);//设置Cron表达式SchedulerFactory schedulerFactory = new StdSchedulerFactory();Scheduler scheduler = schedulerFactory.getScheduler();scheduler.scheduleJob(jobDetail, cronTrigger);scheduler.start();(3)使用Calendar考虑到实现生活中日历上特定日期,如:五一节和国际节等;//法定节日是以每年为周期的,所以使用AnnualCalendarAnnualCalendar holidays = new AnnualCalendar();//五一劳动节Calendar laborDay = new GregorianCalendar();laborDay.add(Calendar.MONTH,5);laborDay.add(Calendar.DA TE,1);holidays.setDayExcluded(laborDay, true); //排除的日期,如果设置为false则为包含//国庆节Calendar nationalDay = new GregorianCalendar();nationalDay.add(Calendar.MONTH,10);nationalDay.add(Calendar.DATE,1);holidays.setDayExcluded(nationalDay, true);//排除该日期scheduler.addCalendar("holidays", holidays, false, false);//向Scheduler注册日历trigger.setCalendarName("holidays");//让Trigger应用指定的日历规则。