Quartz学习-- quartz基本介绍和 Cron表达式

Quartz学习

 

一. Quartz 大致简介

  1. Quartz 是完全由 java 开发的一个开源任务日程管理系统

    ​任务日程管理系统 换句话说就是:

    ​ 一个预先确定的日程时间到达时,负责执行任务的一个系

  2. Quartz用一个.jar 库文件,其包含了所有Quartz的核心功能,

    1. 这些功能有一个主要的接口: Schedule接口

      它提供了简单的操作 例如:

      ​ 将任务纳入日程或者从日程中取消

      ​ 开始/停止/暂停日程进度

  3. 定时器的种类:

    Quartz中有五中类型的Trigger:

    • SimpleTrigger : 用来触发只需执行一次或者在给定时间触发并且重复N次 且每次执行延迟一定时间的任务

    • CronTrigger : 按照日历触发,例如 每个周五 每个月的1号凌晨 2:30

    • DateIntervalTrigger

    • NthIncludedDayTrigger

    • Calendar 类(org.quartz.Calendar)

  4. 存储方式:

    Quartz自身支持 两种存储方式:

    • RAMJobStore (顾明思议 存放在当前内存)

    • JDBCJobStore (通过jdbc实例到数据库)

    对比:

    存储类型 优点 缺点
    RAMJobStore 不需要外部数据库,配置简单,运行速度快 因为调度程序信息存储在jvm 所以jvm程序停止运行时 将有丢失 且因为内存大小也有存储个数限制
    JDBCJobStore 可以存储到数据库中可以控制事物 因为需要连接数据库 所以运行速度有所影响
  5. 表关系及解释

  

   
表名称 说明
qrtz_blob_triggers Trigger作为Blob类型存储(用于Quartz用户用JDBC创建他们自己定制的Trigger类型,JobStore 并不知道如何存储实例的时候)
qrtz_calendars 以Blob类型存储Quartz的Calendar日历信息, quartz可配置一个日历来指定一个时间范围
qrtz_cron_triggers 存储Cron Trigger,包括Cron表达式和时区信息。
qrtz_fired_triggers 存储与已触发的Trigger相关的状态信息,以及相联Job的执行信息
qrtz_job_details 存储每一个已配置的Job的详细信息
qrtz_locks 存储程序的非观锁的信息(假如使用了悲观锁)
qrtz_paused_trigger_graps 存储已暂停的Trigger组的信息
qrtz_scheduler_state 存储少量的有关 Scheduler的状态信息,和别的 Scheduler 实例(假如是用于一个集群中)
qrtz_simple_triggers 存储简单的 Trigger,包括重复次数,间隔,以及已触的次数
qrtz_triggers 存储已配置的 Trigger的信息
qrzt_simprop_triggers  
  1. 核心类和关系

    1. 核心类

      • QuartzSchedulerThread:

        负责执行向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!

  2. 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 时产生的类版本问题
    //org.quartz.jobStore.useProperties : 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 属性的最大值是常量 java.lang.Thread.MAX_PRIORITY,等于10。最小值为常量 java.lang.Thread.MIN_PRIORITY,为1)
    //自创建父线程
    //org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
    //数据库别名
    org.quartz.jobStore.dataSource : qzDS
    //设置数据源
    org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
    org.quartz.dataSource.qzDS.URL:jdbc:mysql://localhost:3306/quartz
    org.quartz.dataSource.qzDS.user:root
    org.quartz.dataSource.qzDS.password:123456
    org.quartz.dataSource.qzDS.maxConnection:10
    

      

  3. JDBC插入表顺序

    主要的JDBC操作类,执行sql顺序: 

    基本顺序:
    记录工作内容  
    插入触发器列表  
    对应类型trigger规则入库  
    存储已触发job信息和trigge信息

    Simple_trigger :插入顺序
    qrtz_job_details ---> qrtz_triggers ---> qrtz_simple_triggers
    qrtz_fired_triggers

    Cron_Trigger:插入顺序
    qrtz_job_details ---> qrtz_triggers ---> qrtz_cron_triggers
    qrtz_fired_triggers

二 . Cron 表达式

  1. 为什么要使用cron表达式

    我们之前提到 有五种触发器归我们使用

    其中常用的 有 SimpleTrigger 和 CronTrigger

    • SimpleTrigger 是完全指定的时间反复进行工作的时间表

  • CronTrigger 却拥有着 充分的可根据日历预定的 方案 且它包含Simple方案中的 初始启动时间

    例如:

    • 每个星期五中午

    • 每个工作日的早上10:30

    • 周三周五 9:00-10:00 每五分钟一次

  1. Cron Expressions

    Cron 表达式并不是只是使用在 Quartz中的 ,实际上它作为一种专门的表达式也应用在Linux的定时任务中 ,以及在java中Spring的@Scheduled注解 也都使用了

    Cron表达式是 字符串形式

    Cron本质上是由七个 子表达式,描述个别细节的时间表 而这些子表达式是由空格分开的

    子表达式:

    位置 意义 有效值 可用特殊字符
    1 Seconds 0-59 , - * /
    2 Minutes 0-59 , - * /
    3 Hours 0 - 23 , - * /
    4 Day-of-Month 1 - 31 ( 注意一些特别的月份) , - * / ? L W
    5 Month 0 - 11 字符串 “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV DEC” , - * /
    6 Day-of-Week(每周) 1 - 7 字符串“SUN, MON, TUE, WED, THU, FRI, SAT”表示 * 注意: 1==SUN , - * / ? L #
    7 Year(年 可选字段) empty 或者 1970-2099 , - * /
    1. 特殊字符

      显然通过子表达式并不能写出一个 重复执行的表达式

      而特殊字符就是来解决当前问题的

    特殊字符 :

    符号 表示 举例说明
    / 与当前子表达式结合使用占用一个子表达式位置 例: "3/15" 放在第二个子表达式位上, 表示第三分钟开始执行,每15分钟执行一次
    ? 某一天 只存在与 Day-of-Month 和 Day-of-Week 中使用,来解决 这两个表达式的冲突问题 在其中一个子表达式有值的情况下 ?写在另一个表达式上表示匹配任意值,这样我们就不会再用* 去来表示匹配任意值了 例: 每月15号的早上4点 : "0 0 4 15 * ?" 每周五晚上11点: "0 0 23 ? * FRI"
    L 每月 或每周 的最后一天 只存在与 Day-of-Month 和 Day-of-Week 中使用, Day-of-Month 子表达式中,“L”表示一个月的最后一天 Day-of-Week 子表达式中,“L”表示一个星期的最后一天,也就是SAT 例: “0 15 10 ? * 6L” 表示 每月最后一个星期五10:15分运行。 "0 15 10 2L * ?" 表示 每月倒数第二天10:15分运行。
    W 最近工作日 只存在与 Day-of-Month 最近的工作日: 例: "0 15 10 15W * ?" 每个月距离15日最近的工作日 如 15日是周六则执行时间是14日 若15日是周日 则执行时间是16 如15号是工作日就15执行 就近匹配不会跨出当前月
    # 第几个星期几 只存在与 Day-of-Week 中 每月第n个工作日 例:“0 15 10 ? * 6#3” 表示每个月第三个星期五 “0 15 10 ? * 4#2” 表示每个月第二个星期三
    , 多个 例: "0 0 0,13,18,21 * * ?": 每天的0点、13点、18点、21点都执行一次:
    - 区间 例: "0 0-5 14 * * ?" : 在每天下午2点到下午2:05期间的每1分钟触发
    * 补位符 补位 但是 注意: Day-of-Month 和 Day-of-Week 肯定有一个为 ? 也不能两个 ?

    综合例子:

    "0 30 0-4 ? 3,7 5#2 2018":

    ​ 每30分钟执行一次

    ​ 凌晨的0-4 点

    ​ 每个月

    ​ 3 月和 7月

    ​ 第二个周四

    ​ 2018年

    ​ : 2018年 的三月和7月的第二个周四的凌晨0-4点 开始每30分钟执行一次

    "0 30 4 10LW * ?":

    ​ 第四位是 Day-of-Month L在此表示 每个月最后

    ​ 10L表示每月的倒数第十天 (不一定是21号 月份不同倒数的第几天也就不同 )​ W表示 附近的工作日

    ​ 所以表示每个月离倒数第十天最近的工作日的凌晨4点30分执行一次

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326462504&siteId=291194637