实现quartz定时器及quartz定时器原理介绍

一、核心概念
 
Quartz的原理不是很复杂,只要搞明白几个概念,然后知道如何去启动和关闭一个调度程序即可。

1、Job
表示一个工作,要执行的具体内容。此接口中只有一个方法
void execute(JobExecutionContext context)

2、JobDetail
JobDetail表示一个具体的可执行的调度程序,Job是这个可执行程调度程序所要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略。

3、Trigger代表一个调度参数的配置,什么时候去调。

4、Scheduler代表一个调度容器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合,就可以被Scheduler容器调度了。

二、一个最简单入门实例

代码如下:

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.Date;

/**
* quartz定时器测试
*
* @author leizhimin 2009-7-23 8:49:01
*/
public class MyJob implements Job {
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
                System.out.println(new Date() + ": doing something...");
        }
}

class Test {
        public static void main(String[] args) {
                //1、创建JobDetial对象
                JobDetail jobDetail = new JobDetail();
                //设置工作项
                jobDetail.setJobClass(MyJob.class);
                jobDetail.setName("MyJob_1");
                jobDetail.setGroup("JobGroup_1");

//2、创建Trigger对象
                SimpleTrigger strigger = new SimpleTrigger();
                strigger.setName("Trigger_1");
                strigger.setGroup("Trigger_Group_1");
                strigger.setStartTime(new Date());
                //设置重复停止时间,并销毁该Trigger对象
                java.util.Calendar c = java.util.Calendar.getInstance();
                c.setTimeInMillis(System.currentTimeMillis() + 1000 * 1L);
                strigger.setEndTime(c.getTime());
                strigger.setFireInstanceId("Trigger_1_id_001");
                //设置重复间隔时间
                strigger.setRepeatInterval(1000 * 1L);
                //设置重复执行次数
                strigger.setRepeatCount(3);

//3、创建Scheduler对象,并配置JobDetail和Trigger对象
                SchedulerFactory sf = new StdSchedulerFactory();
                Scheduler scheduler = null;
                try {
                        scheduler = sf.getScheduler();
                        scheduler.scheduleJob(jobDetail, strigger);
                        //4、并执行启动、关闭等操作
                        scheduler.start();

} catch (SchedulerException e) {
                        e.printStackTrace();
                }
//                try {
//                        //关闭调度器
//                        scheduler.shutdown(true);
//                } catch (SchedulerException e) {
//                        e.printStackTrace();
//                }
        }
}

执行结果:

当把结束时间改为:


代码如下:

//设置重复停止时间,并销毁该Trigger对象
java.util.Calendar c = java.util.Calendar.getInstance();
c.setTimeInMillis(System.currentTimeMillis() + 1000 * 1L);
strigger.setEndTime(c.getTime());

执行结果:

当添加一条关闭调度器的语句:
//4、并执行启动、关闭等操作
scheduler.start();
scheduler.shutdown(true);

程序执行结果:
Thu Jul 23 10:11:50 CST 2009: doing something...

Process finished with exit code 0
仅仅执行了一次,这一次能执行完,原因是设定了scheduler.shutdown(true);true表示等待本次任务执行完成后停止。

从这里也可以看出,scheduler是个容器,scheduler控制jobDetail的执行,控制的策略是通过trigger。

当scheduler容器启动后,jobDetail才能根据关联的trigger策略去执行。当scheduler容器关闭后,所有的jobDetail都停止执行。

三、透过实例看原理

通过研读Quartz的源代码,和本实例,终于悟出了Quartz的工作原理。

1、scheduler是一个计划调度器容器(总部),容器里面可以盛放众多的JobDetail和trigger,当容器启动后,里面的每个JobDetail都会根据trigger按部就班自动去执行。

2、JobDetail是一个可执行的工作,它本身可能是有状态的。

3、Trigger代表一个调度参数的配置,什么时候去调。

4、当JobDetail和Trigger在scheduler容器上注册后,形成了装配好的作业(JobDetail和Trigger所组成的一对儿),就可以伴随容器启动而调度执行了。

5、scheduler是个容器,容器中有一个线程池,用来并行调度执行每个作业,这样可以提高容器效率。

6、将上述的结构用一个图来表示,如下:

四、总结

1、搞清楚了上Quartz容器执行作业的的原理和过程,以及作业形成的方式,作业注册到容器的方法。就认识明白了Quartz的核心原理。

2、Quartz虽然很庞大,但是一切都围绕这个核心转,为了配置强大时间调度策略,可以研究专门的CronTrigger。要想灵活配置作业和容器属性,可以通过Quartz的properties文件或者XML来实现。

3、要想调度更多的持久化、结构化作业,可以通过数据库读取作业,然后放到容器中执行。

4、所有的一切都围绕这个核心原理转,搞明白这个了,再去研究更高级用法就容易多了。

5、Quartz与Spring的整合也非常简单,Spring提供一组Bean来支持:MethodInvokingJobDetailFactoryBean、SimpleTriggerBean、SchedulerFactoryBean,看看里面需要注入什么属性即可明白了。Spring会在Spring容器启动时候,启动Quartz容器。

6、Quartz容器的关闭方式也很简单,如果是Spring整合,则有两种方法,一种是关闭Spring容器,一种是获取到SchedulerFactoryBean实例,然后调用一个shutdown就搞定了。如果是Quartz独立使用,则直接调用scheduler.shutdown(true);

7、Quartz的JobDetail、Trigger都可以在运行时重新设置,并且在下次调用时候起作用。这就为动态作业的实现提供了依据。你可以将调度时间策略存放到数据库,然后通过数据库数据来设定Trigger,这样就能产生动态的调度。

(0)

相关推荐

  • java定时任务的实现方式

    在开发测试工具的应用后台,经常听到同事说要做个定时任务把做日志处理,或者数据清理,包括做些复杂的业务计算逻辑,在选择定时任务的时候,怎么能够快速实现,并且选择一种更适合自己的方式呢? 我这里把定时任务的实现收集整理了一些方法,希望可以帮到刚开始做定时任务的同学,写得不对的地方请指正. 一  Java 基本的定时任务,总结方法有三种: 1.1   创建一个thread,然后让它在while循环里一直运行着,通过sleep方法来达到定时任务的效果: 1.2   用Timer和TimerTask与第一

  • 最流行的java后台框架spring quartz定时任务

    配置quartz 在spring中需要三个jar包: quartz-1.8.5.jar.commons-collections-3.2.1.jar.commons-logging-1.1.jar 首先要配置我们的spring.xml xmlns 多加下面的内容. xmlns:task="http://www.springframework.org/schema/task" 然后xsi:schemaLocation多加下面的内容. http://www.springframework.o

  • Spring整合Quartz实现定时任务调度的方法

    最近项目中需要实现定时执行任务,比如定时计算会员的积分.调用第三方接口等,由于项目采用spring框架,所以这里结合spring框架来介绍. 编写作业类 即普通的pojo,如下: package com.pcmall.task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TaskA { private static Logger logger = LoggerFactory.getLogger(Ta

  • 实现quartz定时器及quartz定时器原理介绍

    一.核心概念 Quartz的原理不是很复杂,只要搞明白几个概念,然后知道如何去启动和关闭一个调度程序即可. 1.Job表示一个工作,要执行的具体内容.此接口中只有一个方法void execute(JobExecutionContext context) 2.JobDetailJobDetail表示一个具体的可执行的调度程序,Job是这个可执行程调度程序所要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略. 3.Trigger代表一个调度参数的配置,什么时候去调. 4.Sched

  • Go Ticker 周期性定时器用法及实现原理详解

    目录 前言 Ticker 应用示例 创建定时器 停止定时器 实现原理 数据结构 runtimeTimer 创建Ticker 停止Ticker Ticker 与 Timer 区别 小结 前言 定时器在Go语言应用中使用非常广泛,Go语言的标准库里提供两种类型的计时器,一种是一次性的定时器Timer,另外一种是周期性的定时器Ticker.本文主要来看一下Ticker的用法和实现原理,需要的朋友可以参考以下内容,希望对大家有帮助. Ticker Ticker是周期性定时器,即周期性的触发一个事件,它会

  • TCP 四种定时器(重传定时器,坚持计时器,保活定时器,时间等待计时器)

    TCP 四种定时器 重传定时器 主要为了防止报文丢失或者阻塞.当A向B发送报文时,就会启动重传定时器,若在定时器到达之后,仍没有收到B的确认报文,则A会重新发送上次发送的报文.同时,令重传定时器复位.继续计时. 坚持计时器 此计时器针对下面场景: 当B向A发送了0窗口报文,B此时已经没有空间接受A发送的数据了,通知A停止发送.A在收到后即停止发送,等待一段时间后,B有了一些空间,可以继续接收了.此时再向A发送非0窗口报文.如果此非0窗口报文在网络中阻塞或者丢失了,那么A将永远以为B没有空间接收数

  • python 定时器,轮询定时器的实例

    python 定时器默认定时器只执行一次,第一个参数单位S,几秒后执行 import threading def fun_timer(): print('Hello Timer!') timer = threading.Timer(1, fun_timer) timer.start() 改成以下可以执行多次 建立loop_timer.py from threading import _Timer class LoopTimer(_Timer): """Call a funct

  • Java多线程Condition接口原理介绍

    Condition接口提供了类似Object的监视器方法,与Lock配合可以实现等待/通知模式,但是这两者在使用方式以及功能特性上还是有差别的 Condition接口详解 Condition定义了等待/通知两种类型的方法,当前线程调用这些方法时,需要提前获取到Condition对象关联的锁.Condition对象是由Lock对象(调用Lock对象的newCondition()方法)创建出来的,换句话说,Condition是依赖Lock对象的. Lock lock = new ReentrantL

  • 网络安全及防御之SQL注入原理介绍

    目录 A.SQL注入概述 什么是SQL注入 SQL注入的原理 SQL注入的地位 SQL注入的来源 SQL注入的主要特点 SQL注入的危害 B.SQL注入攻击 SQL注入攻击 SQL注入威胁表达方式 SQL注入典型攻击手段 SQL注入是否存在注入的判断方式 SQL注入实战步骤 按照注入点类型来分类 按照数据提交的方式来分类 按照执行效果来分类 C.MySQL注入常用函数 MySQL的注释风格 MySQL--union操作符 MySQL--常用函数 MySQL--字符串连接函数 MySQL--inf

  • ThreadLocal原理介绍及应用场景

    本次给大家介绍重要的工具ThreadLocal.讲解内容如下,同时介绍什么场景下发生内存泄漏,如何复现内存泄漏,如何正确使用它来避免内存泄漏. ThreadLocal是什么?有哪些用途? ThreadLocal如何使用 ThreadLocal原理 ThreadLocal使用有哪些坑及注意事项 1. ThreadLocal是什么?有哪些用途? 首先介绍Thread类中属性threadLocals: /* ThreadLocal values pertaining to this thread. T

  • Go语言中的Base64编码原理介绍以及使用

    目录 前言 Go Base64编码 什么是Base64编码 为什么需要Base64编码 Base64编码原理 编码步骤 位数不足情况 Base64解码原理 Base64标准编码变种 总结 前言 在网络中传递参数时,我们经常会对参数进行Base64编码,那么Go 语言中如何进行Base64编码呢?Base64编码的原理是怎样的呢?通过这篇文章一起来了解下吧! Go Base64编码 标准Base64编码 // 标准Base64编码     src := "hello world"   

  • Java中枚举的实现原理介绍

    目录 基本概述 使用方式 条件选择 循环遍历 集合映射 常用方法 总结 基本概述 在 JDK1.5 之前,通过定义常量使用的都是:public static fianl.而枚举的设计,就是把相关的常量分组到一个枚举类型里,方便创建和管理. 比如我们要定义一个颜色常量: public enum Colour { RED, YELLOW, BLUE, GREEN } 这段代码通过底层编译后,实际创建了4个枚举对象: new Enum<EnumTest>("RED", 0); n

  • Docker exec 的实现原理介绍

    我使用了 docker exec 命令进入到了容器当中.在了解了Linux Namespace 的隔离机制后,你应该会很自然地想到一个问题:docker exec 是怎么做到进入容器里的呢?实际上,Linux Namespace 创建的隔离空间虽然看不见摸不着,但一个进程的 Namespace 信息在宿主机上是确确实实存在的,并且是以一个文件的方式存在. 比如,通过如下指令,你可以看到当前正在运行的 Docker 容器的进程号(PID)是 25686: $ docker inspect --fo

随机推荐