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

二模拟案例

【1】定时任务类

 package com.yeepay.sxf.testQuartz;

 import java.util.Map;
/**
* job类,这个类非常简单,只有一个execute方法,该方法是定时job具体执行的内容
* 也就是定时任务
* @author sxf
*
*/
public class Job {
public void exectute(Map<String, String> jobData){
System.out.println("******************");
System.out.println(jobData.get("type")+":Test Job Run at:"+System.currentTimeMillis());
System.out.println("******************");
}
}

【2】定时任务类的详细信息

 package com.yeepay.sxf.testQuartz;

 import java.util.HashMap;
/**
* 定时的详细信息
* 定时的相信信息(1)这个定时信息对应的任务类
* (2)这个定时信息对应的任务类的参数,方法
* @author sxf
*
*/
public class JobDetail { private Class<? extends Job> clazz;
private String jobName;
private HashMap<String, String> jobData; //无参构造
public JobDetail(){
jobData =new HashMap<String, String>();
}
//有参构造
public JobDetail(String name,Class<? extends Job> clazz){
this();
this.jobName=name;
this.clazz=clazz;
} public int hashCode(){
final int prime=31;
int result=1;
result=prime*result+((jobName==null)?0:jobName.hashCode());
return result;
} /**
* 用来通过在list中使用key匹配获取jobdetail
*/
@Override
public boolean equals(Object obj) {
if(this==obj){
return true;
}
if(obj==null){
return false;
}
JobDetail other=(JobDetail) obj;
if(jobName==null){
if(other.jobName!=null){
return false;
}
}else if(!jobName.equals(other.jobName)){
return false;
}
return true;
}
public Class<? extends Job> getClazz() {
return clazz;
}
public void setClazz(Class<? extends Job> clazz) {
this.clazz = clazz;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public HashMap<String, String> getJobData() {
return jobData;
}
public void setJobData(HashMap<String, String> jobData) {
this.jobData = jobData;
} }

【3】定时的触发器

 package com.yeepay.sxf.testQuartz;
/**
* Trigger类,记录下次运行作业的时间和运行job的key
* 一个触发器(1)内部维护一个定时任务的执行策略
* (2)内部同时维护一个定时的详细信息
* (3)触发器和定时详细信息是一对一的关系
* @author sxf
*
*/
public class Trigger implements Comparable { /**
* 定时的详细信息
*/
private String jobKey;
/**
* 定时的执行策略(下次执行时间)
*/
private long nextFireTime; /**
* 在TreeMap中可以根据下次运行时间排序
*/
@Override
public int compareTo(Object o) {
Trigger d=(Trigger) o;
return (int)(this.nextFireTime-d.getNextFireTime());
} /**
* 测试是只想运行一次,使用-1来退出
*/
public void resert(){
setNextFireTime(-1);
} public String getJobKey() {
return jobKey;
} public void setJobKey(String jobKey) {
this.jobKey = jobKey;
} public long getNextFireTime() {
return nextFireTime;
} public void setNextFireTime(long nextFireTime) {
this.nextFireTime = nextFireTime;
} }

【4】定时的初始化类(最关键的类)

 package com.yeepay.sxf.testQuartz;

 import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TreeSet; /**
* Sucheduler类,最重要的类,用来启动和停止框架
* (1)内部维护触发器的集合
* (2)内部维护定时详细信息
* (3)内部维护一个线程类。该线程类是调度定时执行的关键
* @author sxf
*
*/
public class Scheduler { private List<JobDetail> jobList=new ArrayList<JobDetail>();
private TreeSet<Trigger> triggerList=new TreeSet<Trigger>();
private Object lockObject=new Object();
SchedulerThread thread; public void schedulerJob(JobDetail detail,Trigger trigger){
synchronized (lockObject) {
jobList.add(detail);
trigger.setJobKey(detail.getJobName());
triggerList.add(trigger); }
} public void start(){
this.thread=new SchedulerThread(lockObject, triggerList, jobList);
System.out.println("########## run scheduler at:"+new Date()+"##########");
thread.start();
} public void halt(){
thread.halt();
}
}

【5】定时任务调度的线程类

 package com.yeepay.sxf.testQuartz;

 import java.util.List;
import java.util.TreeSet; /**
* 任务调度线程
* (1)从触发器集合中获取触发器
* (2)根据获取的触发器,确认执行策略,和定时的详细信息
* (3)如果符合当前执行策略,则触发器和定时详细信息配合执行定时任务
* @author sxf
*
*/
public class SchedulerThread extends Thread{ private Object lockObject;
private boolean shutDown=false;
private TreeSet<Trigger> triggerList;
private List<JobDetail> jobList; public SchedulerThread(Object lockObject,TreeSet<Trigger> triggerList,List<JobDetail> joblist){
this.lockObject=lockObject;
this.triggerList=triggerList;
this.jobList=joblist;
} @Override
public void run() { while(!shutDown){
synchronized (lockObject) {
try {
//获取最近的触发器
final Trigger trigger=triggerList.pollFirst();//获取最近执行的作业
if(trigger==null){
lockObject.wait(100);
continue;
}
long curr=System.currentTimeMillis();
//从触发器中获取该触发器对应的执行策略
long nextTime=trigger.getNextFireTime();
while(nextTime>curr&&!shutDown){
curr=System.currentTimeMillis();
if(nextTime>curr+1){
lockObject.wait(nextTime-curr);
}
if(!shutDown){
//获取最早的定时任务在集合中的索引
int index=jobList.indexOf(new JobDetail(trigger.getJobKey(), null));
//获取最早的定时
JobDetail jobDetail=jobList.get(index);
//利用反射机制,获取定时任务的类
Job job=jobDetail.getClazz().newInstance();
//执行定时任务
job.exectute(jobDetail.getJobData());
trigger.resert();
nextTime=trigger.getNextFireTime();
if(nextTime!=-1){
triggerList.add(trigger);
}else{
break;
} }
}
} catch (Exception e) {
e.printStackTrace();
}finally{ }
}
}
} public void halt(){
synchronized (lockObject) {
shutDown=true;
lockObject.notifyAll();
}
} }

【6】客户端测试类

 package com.yeepay.sxf.testQuartz;

 /**
* 客户端测试
* 该定时模拟,和jdk自带的TimerTask很相似。
* @author sxf
*
*/
public class ClientTest { public static void main(String[] args) {
final JobDetail detail1=new JobDetail("job1",Job.class);
detail1.getJobData().put("type", "job1");
final JobDetail detail2=new JobDetail("job2",Job.class);
detail2.getJobData().put("type", "job2");
final Trigger trigger1=new Trigger();
trigger1.setNextFireTime(System.currentTimeMillis()+30001);
final Trigger trigger2=new Trigger();
trigger2.setNextFireTime(System.currentTimeMillis()+10001); Scheduler scheduler=new Scheduler();
scheduler.schedulerJob(detail1, trigger1);
scheduler.schedulerJob(detail2, trigger2); scheduler.start();
try {
Thread.sleep(100001);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
scheduler.halt();
}
}

定时组件quartz系列<一>模拟定时组件小程序的更多相关文章

  1. Wuss Weapp 一款高质量,组件齐全,高自定义的微信小程序 UI 组件库

    Wuss Weapp 一款高质量,组件齐全,高自定义的微信小程序 UI 组件库 文档 https://phonycode.github.io/wuss-weapp 扫码体验 使用微信扫一扫体验小程序组 ...

  2. 微信小程序 MinUI 组件库系列之 price 价格组件

    MinUI 是基于微信小程序自定义组件特性开发而成的一套简洁.易用.高效的组件库,适用场景广,覆盖小程序原生框架.小程序组件化框架等,并且提供了高效的命令行工具.MinUI 组件库包含了很多基础的组件 ...

  3. 微信小程序开发系列教程三:微信小程序的调试方法

    微信小程序开发系列教程 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 微信小程序开发系列二:微信小程序的视图设计 这个教程的前两篇文章,介绍了如何用下图所示的微信开发者工具自动生成一个Hel ...

  4. 定时组件quartz系列<三>quartz调度机制调研及源码分析

    quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...

  5. 定时组件quartz系列<二>quartz的原理

    Quartz是一个大名鼎鼎的Java版开源定时调度器,功能强悍,使用方便.   一.核心概念   Quartz的原理不是很复杂,只要搞明白几个概念,然后知道如何去启动和关闭一个调度程序即可.   1. ...

  6. 定时组件quartz系列<二>quartz的集群原理

    1.基本信息:      Quartz是一个开源的作业调度框架,它完全由java写成,并设计用于J2Se和J2EE应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它 来为执行一个作业而创建简单的或 ...

  7. xmlplus 组件设计系列之零 - xmlplus 简介

    xmlplus 是什么 xmlplus 是博主写的一个 JavaScript 框架,用于快速开发前后端项目. xmlplus 基于组件设计,组件是基本的构造块.评价组件设计好坏的一个重要标准是封装度. ...

  8. 两百条微信小程序跳坑指南(不定时更新)

    微信小程序联盟出品 跳坑textarea<二百二十三>不显示文本及textarea相关问题集合跳坑<二百一十三> background-image无法获取本地资源图片....跳 ...

  9. 微信小程序~基础组件

    (1)视图容器 名称 功能说明 movable-view 可移动的视图容器,在页面中可以拖拽滑动 cover-image 覆盖在原生组件之上的图片视图 cover-view 覆盖在原生组件之上的文本视 ...

随机推荐

  1. HDU5597/BestCoder Round #66 (div.2) GTW likes function 打表欧拉函数

    GTW likes function      Memory Limit: 131072/131072 K (Java/Others) 问题描述 现在给出下列两个定义: f(x)=f_{0}(x)=\ ...

  2. MongoDB (八) MongoDB 文档操作

    一. MongoDB 插入文档 insert() 方法 要插入数据到 MongoDB 集合,需要使用 MongoDB 的  insert() 或 save() 方法. 语法 insert() 命令的基 ...

  3. -ffunction-sections -Wl,--gc-sections

    AVR/GCC设置不链接未调用的函数 http://blog.csdn.net/shevsten/article/details/7049688 在AVR Studio4/5的AVR/GCC默认设置下 ...

  4. 一个tomcat上放多个webapp问题,那这多个webapp会不会竞争端口呢?不会!安全两码事

    1.一个tomcat上放多个webapp问题,那这多个webapp会不会竞争端口呢?不会!安全两码事

  5. threadlocal精髓是为每一个线程保证一个共享对象,保证一个,保证是同一个

    threadlocal精髓是为每一个线程保证一个共享对象,保证一个,保证同一个线程中是同一个共享对象. 如果是静态变量是共享的话,那必须同步,否则尽管有副本,还是会出错,故C错

  6. SSIS ->> 生成时间格式

    有时我们需要生成一个文件,文件名的构成是当前时间的特定字符串格式,如yyyyMMddHHmmss 当前时间变成yyyyMMddHHmmss这个格式: (DT_WSTR,4) YEAR(GETDATE( ...

  7. [c/c++]指针数组 pk 数组指针

    首先强调 指针数组归根结底是个数组:数组指针归根结底是个指针. 数组指针 以int (*int)[10]为例 ()的优先级大于[],因此首先它是一个指针,它指向一个数组,数组的维数是10.因此数组指针 ...

  8. 可视化MNIST之降维探索Visualizing MNIST: An Exploration of Dimensionality Reduction

    At some fundamental level, no one understands machine learning. It isn’t a matter of things being to ...

  9. wait、waitpid 僵尸进程 孤儿进程

    man wait: NAME wait, waitpid, waitid - wait for process to change state SYNOPSIS #include <sys/ty ...

  10. ajax练习习题三搜索

    做一个汽车搜索页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...