10 -- 深入使用Spring -- 5...1 使用Quartz
10.5.1 使用Quartz
JDK为简单的任务调度提供了Timer支持。
Quartz是一个任务调度框架。借助于Cron表达式,Quartz可以支持各种复杂的任务调度。
1.下载和安装Quartz
⊙ docs : 存放Quartz的相关文档,包括API等文档。
⊙ examples : 存放Quartz的示例程序。
⊙ javadoc : 存放Quartz的API文档。
⊙ lib : 存放Quartz的JAR包,以及Quartz编译或运行所依赖的第三方类库。
⊙ src : 存放Quartz 的源文件。
⊙ 其他Quartz 相关说明文档。
提示: 实际上Quartz还是用的SLF4J作为日志工具,因此还需要将lib/子目录下与SLF4J相关的JAR包复制到项目的类加载路径中。
2.Quartz运行的基本属性
Quartz 允许提供一个名为quartz.properties的配置文件,通过该配置文件,可以修改框架运行时的环境。默认使用quartz-x.x.x.jar里的quartz.properties文件(在该压缩文件的org\quartz路径下)。如果需要改变默认的Quartz属性,程序可以自己创建一个quartz.properties文件,并将它放在系统的类加载路径下,ClassLoader会自动加载并启用其中的各种属性。
properties : quartz
- # Default Properties file for use by StdSchedulerFactory
- # to create a Quartz Scheduler Instance, if a different
- # properties file is not explicitly specified.
- #
- # 配置主调度器属性
- org.quartz.scheduler.instanceName: DefaultQuartzScheduler
- org.quartz.scheduler.rmi.export: false
- org.quartz.scheduler.rmi.proxy: false
- org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
- # 配置线程池
- # Quartz 线程池的实现类
- org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
- # 线程池的线程数量
- org.quartz.threadPool.threadCount: 1
- # 线程池里线程的优先级
- org.quartz.threadPool.threadPriority: 5
- org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
- # 配置作业存储
- org.quartz.jobStore.misfireThreshold: 60000
- org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
Quartz 提供两种作业存储方式:
⊙ 第一种类型叫作RAMJobStore,它利用内存来持久化调度程序信息。这种作业存储类型最容易配置和运行。对于许多应用来说,这种存储方式已经足够了。然而由于调度程序信息保存在JVM的内存里面,因此,一旦应用程序中止,所有的调度信息就会丢失。
⊙ 第二种类型称为JDBC作业存储,需要JDBC驱动程序和后台数据保存调度程序信息,由需要调度程序维护调度信息的用户来设计。
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore 指定使用RAMJobStore存储方式。
org.quartz.threadPool.threadCount: 10 指定Quartz线程池的线程数为1,即系统Quartz最多启动1条线程来执行指定任务。如果此处指定更大的线程数,程序将会启动更多的线程来执行指定的任务,这意味着系统可能有多个任务并发执行。
3.Quartz里的作业
作业是一个执行指定任务的Java类,当Quartz调用某个Java任务执行时,实际上就是执行该任务对象的execute()方法,Quartz里的作业类需要实现org.quartz.Job接口,该Job接口包含了一个方法execute(),execute()方法体是被调度的作业体。
一旦实现了Job接口和execute()方法,当Quartz调度作业运行时,该execute()方法就会自动运行起来。
Class : TestJob
- package edu.pri.lime.quartz;
- import java.util.Date;
- import org.quartz.Job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- public class TestJob implements Job {
- // 判断作业是否执行的旗标
- // 该旗标保证作业不会被重复执行
- private boolean isRunning = false;
- @Override
- public void execute(JobExecutionContext Context) throws JobExecutionException {
- // 如果作业没有被调度
- if (!isRunning) {
- System.out.println(new Date() + " 作业被调度");
- for (int i = 0; i < 100; i++) {
- System.out.println("作业完成" + (i + 1) + "%");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println(new Date() + " 作业调度结束");
- } else {
- // 如果作业正在执行,即使获得调度,也立即退出
- System.out.println(new Date() + "任务退出");
- }
- }
- }
4.Quartz里的触发器
Quartz允许作业与作业调度分离,Quartz使用触发器将任务与任务调度分离开,Quartz中的触发器用来指定任务的被调度时机,其框架提供了一系列触发器类型,但以下两种是最常用的:
⊙ SimpleTrigger : 主要用于简单的调度。例如,如果需要在给定的时间内重复执行作业,或者间隔固定时间执行作业,则可以选择SimpleTrigger。SimpleTrigger类似于JDK的Timer。
⊙ CronTrigger : 用于执行更复杂的调度。该调度器基于Calendar-like。例如,需要在除星期六和星期日以外的每天上午10:30调度某个任务时,则应该使用CronTrigger。CronTrigger是基于Unix Cron的表达式。
Cron表达式是一个字符串,字符串以5个或6个空格隔开,分成6个或7个域,每个域代表一个时间域。Cron表达式有如下两种语法格式:
⊙ 包含7个域的Cron表达式:
- Seconds Minutes Hours DayofMonth Month DayofWeek Year
⊙ 包含6个域的Cron表达式:
- Seconds Minutes Hours DayofMonth Month DayofWeek
每个域可出现的字符如下:
⊙ Seconds : 可出现 , - * / 四个特殊字符和数字,有效范围为0~59的整数。
⊙ Minutes : 可出现 , - * / 四个特殊字符和数字,有效范围为0~59的整数。
⊙ Hours : 可出现 , - * / 四个特殊字符和数字,有效范围为0~23的整数。
⊙ DayofMonth : 可出现 , - * ? / L W C 八个特殊字符和数字,有效范围为1~31的整数。
⊙ Month : 可出现 , - * / 四个特殊字符和数字,有效范围为1~12的整数或JAN-DEC。
⊙ DayofWeek : 可出现 , - * ? / L C # 八个特殊字符和数字,有效范围为1~7或SUN-SAT。其中1表示星期日,2表示星期一,以此类推。
⊙ Year : 可出现 , - * / 四个特殊字符和数字,有效范围为1970~2099的整数。
每个域通常都使用数字,但还可以出现如下特殊字符,它们的含义如下:
⊙ * : 表示匹配该域的任意值。假如在Minutes域使用*,即表示每分钟都会触发事件。
⊙ ? : 表示用在DayofMonth和DayofWeek 两个域。它们会匹配该域的任意值,但实际应用中则不会,因为DayofMonth和DayofWeek会互相影响。例如,想在每个月的20日触发调度,无论20日是星期几,则只能使用如下写法:13 13 15 20 * ?,其中最后以为只能使用?,而不能使用*;如果使用*,则表示无论星期几都会触发,但实际并不是这样的。
⊙ - : 表示范围。例如,在Minutes域使用5-20,表示从5分钟到20分钟内每分钟触发一次。
⊙ / : 表示从起始时间开始触发,然后每隔固定时间触发一次。例如,在Minutes域使用5/20,则意味着在5分钟时触发一次,而在25、45等分钟时分别触发一次。
⊙ , : 表示列出枚举值。例如,在Minutes域使用5,20,则意味着在5和20分钟分别触发一次。
⊙ L : 表示最后。只能出现在DayofWeek和DayofMonth域,如果在DayofWeek域使用5L,则意味着在最后一个星期四触发。
⊙ W : 表示有效工作日(星期一到星期五)。只能出现在DayofMonth域,系统将离指定日期最近的有效工作日触发时间。例如,在DayofMonth域使用5W,如果5日是星期六,则将在最近的工作日星期一,即4日触发;如果5日是星期一到星期五中的一天,则就在5日触发。需要注意的是,W不会跨月寻找,例如,1W,1日恰好是星期六,系统不会在上月的最后一天触发,而是到3日触发。
⊙ LW : 这两个字符可以连接使用,表示某个月最后一个工作日,即最后一个星期五。
⊙ # : 用于确定每个月的第几个星期几,只能出现在DayofMonth域。例如4#5,表示某月的第5个星期三。
- 表示在周一到周五的每天上午10点15分调度任务
- 0 15 10 ? * MON-FRI
- 表示在2002-2005年中每个月的最后一个星期五上午10点15分调度该任务
- * 15 10 ? * 6L 2002-2005
5.Quartz 里的调度器
调度器用于将任务与触发器关联起来,一个任务可关联多个触发器,一个触发器也可用于控制多个任务。当一个任务关联多个触发器时,每个触发器被激发时,这个任务都会被调度一次;当一个触发器控制多个任务时,此触发器被触发时,所有关联到该触发器的任务都将被调度。
Quartz的调度器由Scheduler接口体现。该接口声明了如下方法:
⊙ void addJob(JobDetail jobDetail,boolean replace) : 将给定的JobDetail实例添加到调度器里。
⊙ Date scheduleJob(JobDetail jobDetail,Trigger trigger) : 将指定的JobDetail实例与给定的trigger关联起来,即使用该trigger来控制该任务。
⊙ Date scheduleJob(Trigger trigger) : 添加触发器trigger来调度作业。
Class : MyQuartzServer
- package edu.pri.lime.quartz;
- import org.quartz.JobBuilder;
- import org.quartz.JobDetail;
- import org.quartz.Scheduler;
- import org.quartz.SchedulerException;
- import org.quartz.SimpleScheduleBuilder;
- import org.quartz.Trigger;
- import org.quartz.TriggerBuilder;
- import org.quartz.TriggerKey;
- import org.quartz.impl.StdSchedulerFactory;
- public class MyQuartzServer {
- public static void main(String[] args) {
- MyQuartzServer server = new MyQuartzServer();
- try {
- server.startScheduler();
- } catch (SchedulerException e) {
- e.printStackTrace();
- }
- }
- // 执行调度
- private void startScheduler() throws SchedulerException {
- // 使用工厂创建调度器实例
- Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
- // 以Job实现类创建JobDetail实例
- JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity("fkJob").build();
- // 创建Trigger对象,该对象代表一个简单的调度器
- // 指定该任务被重复调度50次,每次间隔60秒
- Trigger trigger = TriggerBuilder.newTrigger().withIdentity(TriggerKey.triggerKey("fkTrigger","fkTriggerGroup")).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(60).repeatForever()).startNow().build();
- // 调度器将作业与trigger关联起来
- scheduler.scheduleJob(jobDetail, trigger);
- // 开始调度
- scheduler.start();
- }
- }
程序并没有使用CronTrigger来控制任务的调度,只是使用了一个SimpleTrigger来控制任务的调度。
注意:
使用JobDetail包装一个作业,在包装时,包括作业命名,以及指定作业所在的组。
啦啦啦
10 -- 深入使用Spring -- 5...1 使用Quartz的更多相关文章
- Spring研磨分析、Quartz任务调度、Hibernate深入浅出系列文章笔记汇总
Spring研磨分析.Quartz任务调度.Hibernate深入浅出系列文章笔记汇总 置顶2017年04月27日 10:46:45 阅读数:1213 这系列文章主要是对Spring.Quartz.H ...
- spring多个定时任务quartz配置
spring多个定时任务quartz配置 <?xml version=”1.0″ encoding=”UTF-8″?> <beans xmlns=”http://www.spring ...
- SpringBoot系列:Spring Boot集成定时任务Quartz
一.关于Quartz Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.在java企业级应用中,Q ...
- spring利用javamail,quartz定时发送邮件 <转>
原文地址:spring利用javamail,quartz定时发送邮件 <转>作者:物是人非 spring提供的定时发送邮件功能,下面是一个简单的例子以供大家参考,首先从spring配置文件 ...
- Spring/Spring boot正确集成Quartz及解决@Autowired失效问题
周五检查以前Spring boot集成Quartz项目的时候,发现配置错误,因此通过阅读源码的方式,探索Spring正确集成Quartz的方式. 问题发现 检查去年的项目代码,发现关于QuartzJo ...
- 10 -- 深入使用Spring -- 5...2 在Spring中使用Quartz
10.5.2 在Spring中使用Quartz Spring 的任务调度抽象层简化了任务调度,在Quartz基础上提供了更好的调度抽象.本系统使用Quartz框架来完成任务调度,创建Quartz的作业 ...
- Spring 4.2.5 + Quartz 2.2.0整合
jar包使用的Maven库管理的,在这就不罗列了,注意下只有spring3.x以上的版本才支持quartz2.x的版本. 配置文件: <?xml version="1.0" ...
- 任务调度--spring下的任务调度quartz
之前写过Timer实现任务调度,这篇文章用来写一下在spring下使用quartz实现任务调度,直接上代码: 定义任务对象: package com; /** * 1. 定义任务对象 * * @aut ...
- spring boot1.0 集成quartz 动态配置定时任务
转载自 https://www.imooc.com/article/36278 一.Quartz简介了解 Quartz Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应 ...
随机推荐
- 【linux】——linux僵死进程的产生与避免
一个进程在调用exit命令结束自己的生命的时候,其实它并没有真正的被销毁, 而是留下一个称为僵死进程(Zombie)的数据结构(系统调用exit,它的作用是使进程退出,但也仅仅限于将一个正常的进程变成 ...
- 【IntelliJ IDEA】idea上提交代码到GitHub,已经提交了 但是GitHub上却没有的解决办法
摘要: 今天提交idea上的代码到GitHub,提交过程已经完成, 在版本控制的Log中可以看到,已经将这一部分都提交更新了 在版本控制的Local Changes中已经看不到提交过的代码了 ...
- Spring cloud系列十四 分布式链路监控Spring Cloud Sleuth
1. 概述 Spring Cloud Sleuth实现对Spring cloud 分布式链路监控 本文介绍了和Sleuth相关的内容,主要内容如下: Spring Cloud Sleuth中的重要术语 ...
- SpringBoot2 上传文件 上传多文件
项目结构: 1.单文件上传 upload.html <!DOCTYPE html> <html lang="en"> <head> <me ...
- Docker run 命令的使用方法
[编者的话]在Docker中,run应该是用户使用最多的命令了,很多读者反馈不是很明白run命令的用法,而且相关的书籍.中文资料中对run命令的描述也不是非常完整,所以DockerOne组织翻译了Do ...
- Elasticsearch与Solr 选型
转自:http://blog.csdn.net/jameshadoop/article/details/44905643 搜索引擎选择: Elasticsearch与Solr 搜索引擎选型调研文档 E ...
- linux update & upgrade
Linux升级命令有两个分别是yum upgrade和yum update, 这个两个命令是有区别的: 复制代码 代码如下: yum -y update 升级所有包同时也升级软件和系统内核 复制代码 ...
- 【转】【Html】Vuejs2.0学习之二(Render函数,createElement,vm.$slots,函数化组件,模板编译,JSX)
1.Render函数 所以直接来到Render,本来也想跳过,发现后面的路由貌似跟它还有点关联.先来看看Render 1.1 官网一开始就看的挺懵的,不知道讲的是啥,动手试了一下,一开头讲的是Rend ...
- substitute 命令与 global 命令
他们是很强大的EX命令: substitute的格式: :[range]s[ubstitute]/{pattern}/{string}/{flags} 其中的patttern 指的是正则表达式的匹配: ...
- Linux中几个与文档相关的命令
一.介绍 本文将介绍几个与文档相关的命令 软件环境: 物理机 Windows 8.0 虚拟机 VMware Workstation 12 Linux系统 CentOS 7.3 二.命令cat 命令ca ...