一、Quartz基本概念
Quartz 是 OpenSymphony开源组织在任务调度领域的一个开源项目,完全基于 Java 实现。该项目于 2009 年被 Terracotta 收购,目前是 Terracotta 旗下的一个项目。读者可以到 http://www.quartz-scheduler.org/站点下载 Quartz 的最新发布版本及其源代码。QCT系统使用的是版本 1.6.0,因此本文内容基于该版本。本文不仅介绍如何应用 Quartz 进行开发,也对其内部实现原理作一定讲解。
二、Quartz的特点
在Quartz中,有两类线程,Scheduler调度线程和任务执行线程,其中任务执行线程通常使用一个线程池维护一组线程。线程图如下:
Scheduler调度线程主要有两个:执行常规的线程和执行misfired trigger的线程。常规调度线程轮询存储的所有Trigger,如果有需要触发的trigger,即到达了下一个触发时间,则从任务执行线程池中获取一个空闲线程,执行与该trigger关联的任务。Misfire线程是扫描所有的trigger,查看是否有misfired trigger,如果有就根据misfire的策略分别处理。下图描述了这两个线程的基本流程
以上是run的最开头的一段,不难看出这是在等待scheduler的start,实际上Quartz就是通过线程的wait或sleep来实现时间调度。继续看代码:
这段代码是从jobStore里拿到下一个要执行的trigger,一般情况下jobStore使用的是RAMJobStore,即trigger等相关信息存放在内存里,如果需要把任务持久化就得使用可持久化JobStore。继续看代码:
此段代码是计算下一个trigger的执行时间和现在系统时间的差,然后通过循环线程sleep的方式暂停住此线程,一直等到trigger的执行时间点。继续看代码:
此段代码就是包装trigger,然后通过以JobRunShell为载体,在threadpool里执行trigger所关联的jobDetail。
Quartz数据表
七、 Quartz与Spring集成
第一种方式的Java代码:
方法二、借助于Spring的org.springframework.scheduling.quartz.JobDetailBean的类功能,继承 Spring封装Quartz的org.springframework.scheduling.quartz.QuartzJobBean类,实现 executeInternal方法,executeInternal方法中调用业务类。
第二种方式的Java代码:
八、 企业级开发中常见应用
在应用Quartz进行企业级的开发是,有些问题会经常遇到。下面介绍企业开发中常见的一些问题及通常的解决办法:
应用一:如何使用不同类型的Trigger
前面我们提到Quartz中三种类型的Trigger:SimpleTrigger,CronTrigger,NthIncludedDayTrigger。
SimpleTrigger一般用于实现每隔一定时间执行任务,以及重复多少次,如每2小时执行一次,重复执行5次。SimpleTrigger内部实现机制是通过计算间隔时间来计算下次的执行时间,这就导致其不合适调度定时的任务。例如我们想每天的8:00AM执行任务,如果使用SimpleTrigger的话间隔时间就是一天。主要这里就有一个问题,即当有misfired的任务并且恢复执行时,该执行时间是随机的(取决于何时执行misfired的任务,例如某天的9:00PM)。这会导致之后每天的执行时间都会变成9:00PM,而不是我原来期望的8:00AM。
CronTrigger类似于Linux上的任务调度命令crontab,即利用一个包含7个字段的表达式来表示时间调度方式。例如,“0 15 10 * * ? *”表示每天的10:15AM执行任务。对于涉及到星期和月份的调度,CronTrigger是最合适的,甚至某些情况下是唯一选择。例如,“0 10 14 ? 3 WED”表示三月份的每个星期三的下午14:10PM执行任务。使用者可以在具体用的该trigger时再详细了解每个字段的含义。
NthIncludedDayTrigger的用途比较简单明确,即用于每间隔一个周期的第几天调度任务,例如,每个月的第2天执行指定的任务。
应用二:使用有状态(StatefulJob)还是无状态的任务(Job)
在Quartz中,Job是一个接口,企业应用需要实现这个接口定义自己的任务。基本来说,任务分为有状态和无状态两种。实现Job接口的任务缺省为无状态的。Quartz中还有另外一个接口StatefulJob。实现StatefulJob接口的任务为有状态的,下图列出了Quartz中Job接口的定义以及一些自带的实现类:
无状态任务一般指可以并发的任务,即任务之间是独立的不会相互干扰。例如我们定义一个trigger,每2分钟执行一次,但是某些情况下一个任务可能需要3分钟才能执行完,这样,在上一个任务还处在执行状态时,下一次触发时间已经到了。对于无状态任务,只要触发时间到了就会被执行,因为几个相同任务可以并发执行。但是对于有状态任务来说,是不能并发执行的,同一时间只能有一个任务在执行。
如某些任务需要对数据库中的数据进行增删改处理。这些任务不能并发执行,否则会造成数据混乱。因此我们使用StatefulJob接口。现在回到上面的例子,任务每 2 分钟执行一次,若某次任务执行了 5 分钟才完成,Quartz 会怎么处理呢?按照 trigger 的规则,第 2 分钟和第 4 分钟分别会有一次预定的触发执行,但是由于是有状态任务,因此实际不会被触发。在第 5 分钟第一次任务执行完毕时,Quartz 会把第 2 和第 4 分钟的两次触发作为 misfired job 进行处理。对于 misfired job,Quartz 会查看其 misfire 策略是如何设定的,如果是立刻执行,则会马上启动一次执行,如果是等待下次执行,则会忽略错过的任务,而等待下(即第 6 分钟)触发执行。
应用三:如何设置Quartz的线程池和并发任务
应用四:如何处理Misfired任务
在Quartz应用中,misfired job是经常遇到的情况,一般来说,下面这些原因可能造成misfired job:
1)系统因为某些原因被重启。在系统关闭到重启之间的一段时间里,可能有些任务会被misfire;
2)Trigger被暂停(pause)的一段时间里,有些任务可能会被misfire;
3)线程池中所有线程都被占用,导致任务无法被触发执行,造成misfire;
4)有状态任务在下次触发时间到达时,上次执行还没有结束;
为了处理misfired job,Quartz中为trigger定义了处理策略,主要有下面两种:
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW:针对 misfired job 马上执行一次;
MISFIRE_INSTRUCTION_DO_NOTHING:忽略 misfired job,等待下次触发。
相关推荐
### 深入解读Quartz的原理 #### 一、Quartz概述 Quartz 是一个功能强大且易于使用的 Java 开源定时任务调度器。它能够触发在指定的时间执行任务(通常称为作业)。Quartz 能够满足从简单的到非常复杂的业务场景...
Quartz是Java领域的一款强大的任务调度框架,常用于在应用程序中安排周期性的任务执行。它提供了灵活的时间表定义,支持简单任务和复杂的作业链,并且能够与其他Java应用服务器集成。这篇博客“quartz源码解析(一)”...
在第11章的翻译初稿中,我们可能会深入探讨Quartz的核心概念、设计模式以及如何在实际项目中应用它。下面是对这个章节内容的详细解读。 一、Quartz简介 Quartz是Java领域的一个强大且灵活的任务调度库,它能够管理...
【定时器quartz】是一种广泛应用于Java环境中的开源任务调度框架,它允许程序在特定时间执行预定的任务。Quartz的核心功能是创建、管理和执行作业(Job)和触发器(Trigger)。作业代表要执行的任务,而触发器则定义...
这个"Quzart开发demo"包含了一系列的资源,帮助开发者深入理解和实践Quartz的开发与配置。以下是对这些资源内容的详细解读: 1. **Quartz开发指南.pdf**: 这份PDF文档通常会提供Quartz的全面介绍,包括其核心概念...
Quartz是一种透明度极高的材料,常用于光学应用,尤其是作为闪烁体。PMT则是一种能够将光信号转换为电信号的高灵敏度探测器,对于低强度光信号有很好的响应。 2. **光传播模拟**:该工具能够模拟光子在Quartz等介质...
一种电化学阻抗和石英微天平联用的分析装置及方法”涉及的是电子技术与分析仪器的交叉领域,具体来说,是电化学阻抗谱(Electrochemical Impedance Spectroscopy, EIS)与石英晶体微天平(Quartz Crystal ...
译文可能会包含对原论文的深入解读,或者对所用技术的详细解释。 总的来说,这个资源包为Java开发者提供了一个完整的OA系统实例,不仅可以作为学习Java编程和企业级应用开发的实战案例,还可以帮助理解办公自动化...
这份《Spring开发参考手册》将帮助开发者深入理解Spring框架的各个组件,学习如何利用它们构建高质量、可扩展的Java应用。PDF文档中应该包含详细的API说明、示例代码和最佳实践,是Spring开发者必备的参考资料。通过...
《iPhone开发秘籍第二版》是一本深入探讨iOS应用程序开发的专业书籍,涵盖了从第13章到第21章的源代码。这些章节通常涉及高级iOS开发技术,包括UI设计、网络编程、数据存储、多线程、动画、游戏开发以及性能优化等...
以下是对这些知识点的详细解读: 1. **地图**:在iOS应用开发中,地图功能是不可或缺的。苹果提供了自家的地图服务(MapKit框架),开发者可以利用它来集成地图到应用程序中,实现定位、导航、路径规划等功能。...
最后,报告生成模块将分析结果以可视化的方式呈现给用户,以便于理解和解读。 在技术实现上,系统可能会采用以下组件: 1. **数据库管理**:Springboot与MyBatis或JPA结合,可以方便地操作数据库,如MySQL、Oracle...
《Spring Boot Cookbook(2015.09)源码》是针对Spring Boot框架的一份实践性教程,包含了丰富的代码示例,旨在帮助开发者深入理解并掌握Spring Boot的核心特性和应用。Spring Boot是由Pivotal团队开发的一个Java框架...
本文将详细介绍Spring2.5中的定时器任务配置方法,并通过示例代码进行深入解析。 #### 二、定时任务的核心组件介绍 在Spring2.5中,定时任务主要依赖以下几个核心组件: 1. **`ThreadPoolTaskExecutor`**:这是...
IQAN(Interactive Quartz Application Network)是一个先进的监控和控制系统的品牌,常用于重型机械设备如卡车、挖掘机等。CANBUS(Controller Area Network Bus)则是一种串行通信协议,广泛应用于汽车电子系统,...
- 源码分析有助于深入理解SpringBoot和Vue.js的结合使用,以及如何设计和实现一个完整的Web应用。 6. **技术栈拓展**: - 数据库:可能使用MySQL、PostgreSQL等,配合JPA或MyBatis进行数据访问操作。 - 安全:...
Cron表达式是Unix/Linux系统中的定时任务调度器Cron所使用的语法,也被广泛应用于Java世界,例如Quartz、Spring等框架。它允许用户以字符串的形式定义任务的执行时间,如分钟、小时、日期等。这个压缩包文件包含了对...
Java开发典型模块大全,这是一份专为Java开发者准备的宝贵资源,包含了20个不同类型的Java项目,每个项目都提供了完整的程序源码,旨在帮助开发者深入理解和掌握Java编程的各种核心概念和技术。以下是对这些模块及其...
以下是对这些问题的详细解读: 1. **什么是Spring框架?** Spring是一个开源的Java平台,它为构建企业级应用提供了全面的框架支持,包括依赖注入、面向切面编程(AOP)、数据访问、事务管理等。 2. **依赖注入...