zoukankan      html  css  js  c++  java
  • 定时组件quartz系列<一>模拟定时组件小程序

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

    二模拟案例

    【1】定时任务类

     1 package com.yeepay.sxf.testQuartz;
     2 
     3 import java.util.Map;
     4 /**
     5  * job类,这个类非常简单,只有一个execute方法,该方法是定时job具体执行的内容
     6  * 也就是定时任务
     7  * @author sxf
     8  *
     9  */
    10 public class Job {
    11     public void exectute(Map<String, String> jobData){
    12         System.out.println("******************");
    13         System.out.println(jobData.get("type")+":Test Job Run at:"+System.currentTimeMillis());
    14         System.out.println("******************");
    15     }
    16 }
    View Code

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

     1 package com.yeepay.sxf.testQuartz;
     2 
     3 import java.util.HashMap;
     4 /**
     5  * 定时的详细信息
     6  * 定时的相信信息(1)这个定时信息对应的任务类
     7  *                           (2)这个定时信息对应的任务类的参数,方法
     8  * @author sxf
     9  *
    10  */
    11 public class JobDetail {
    12 
    13     private Class<? extends Job> clazz;
    14     private String jobName;
    15     private HashMap<String, String> jobData;
    16     
    17     //无参构造
    18     public JobDetail(){
    19         jobData =new HashMap<String, String>();
    20     }
    21     //有参构造
    22     public JobDetail(String name,Class<? extends Job> clazz){
    23         this();
    24         this.jobName=name;
    25         this.clazz=clazz;
    26     }
    27     
    28     public int hashCode(){
    29         final int prime=31;
    30         int result=1;
    31         result=prime*result+((jobName==null)?0:jobName.hashCode());
    32         return result;
    33     }
    34     
    35     /**
    36      * 用来通过在list中使用key匹配获取jobdetail
    37      */
    38     @Override
    39     public boolean equals(Object obj) {
    40         if(this==obj){
    41             return true;
    42         }
    43         if(obj==null){
    44             return false;
    45         }
    46         JobDetail other=(JobDetail) obj;
    47         if(jobName==null){
    48             if(other.jobName!=null){
    49                 return false;
    50             }
    51         }else if(!jobName.equals(other.jobName)){
    52             return false;
    53         }
    54         return true;
    55     }
    56     public Class<? extends Job> getClazz() {
    57         return clazz;
    58     }
    59     public void setClazz(Class<? extends Job> clazz) {
    60         this.clazz = clazz;
    61     }
    62     public String getJobName() {
    63         return jobName;
    64     }
    65     public void setJobName(String jobName) {
    66         this.jobName = jobName;
    67     }
    68     public HashMap<String, String> getJobData() {
    69         return jobData;
    70     }
    71     public void setJobData(HashMap<String, String> jobData) {
    72         this.jobData = jobData;
    73     }
    74     
    75     
    76 }
    View Code

    【3】定时的触发器

     1 package com.yeepay.sxf.testQuartz;
     2 /**
     3  * Trigger类,记录下次运行作业的时间和运行job的key
     4  * 一个触发器(1)内部维护一个定时任务的执行策略
     5  *                     (2)内部同时维护一个定时的详细信息
     6  *                     (3)触发器和定时详细信息是一对一的关系
     7  * @author sxf
     8  *
     9  */
    10 public class Trigger implements Comparable {
    11 
    12     /**
    13      * 定时的详细信息
    14      */
    15     private String jobKey;
    16     /**
    17      * 定时的执行策略(下次执行时间)
    18      */
    19     private long nextFireTime;
    20     
    21     /**
    22      * 在TreeMap中可以根据下次运行时间排序
    23      */
    24     @Override
    25     public int compareTo(Object o) {
    26         Trigger d=(Trigger) o;
    27         return (int)(this.nextFireTime-d.getNextFireTime());
    28     }
    29 
    30     /**
    31      * 测试是只想运行一次,使用-1来退出
    32      */
    33     public void resert(){
    34         setNextFireTime(-1);
    35     }
    36     
    37     public String getJobKey() {
    38         return jobKey;
    39     }
    40 
    41     public void setJobKey(String jobKey) {
    42         this.jobKey = jobKey;
    43     }
    44 
    45     public long getNextFireTime() {
    46         return nextFireTime;
    47     }
    48 
    49     public void setNextFireTime(long nextFireTime) {
    50         this.nextFireTime = nextFireTime;
    51     }
    52 
    53 
    54     
    55 }
    View Code

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

     1 package com.yeepay.sxf.testQuartz;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Date;
     5 import java.util.List;
     6 import java.util.TreeSet;
     7 
     8 
     9 
    10 /**
    11  * Sucheduler类,最重要的类,用来启动和停止框架
    12  * (1)内部维护触发器的集合
    13  * (2)内部维护定时详细信息
    14  * (3)内部维护一个线程类。该线程类是调度定时执行的关键
    15  * @author sxf
    16  *
    17  */
    18 public class Scheduler {
    19 
    20     private List<JobDetail> jobList=new ArrayList<JobDetail>();
    21     private TreeSet<Trigger> triggerList=new TreeSet<Trigger>();
    22     private Object lockObject=new Object();
    23      SchedulerThread thread;
    24     
    25     public void schedulerJob(JobDetail detail,Trigger trigger){
    26         synchronized (lockObject) {
    27             jobList.add(detail);
    28             trigger.setJobKey(detail.getJobName());
    29             triggerList.add(trigger);
    30             
    31         }
    32     }
    33     
    34     public void start(){
    35         this.thread=new SchedulerThread(lockObject, triggerList, jobList);
    36         System.out.println("########## run scheduler at:"+new Date()+"##########");
    37         thread.start();
    38     }
    39     
    40     public void halt(){
    41         thread.halt();
    42     }
    43 }
    View Code

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

     1 package com.yeepay.sxf.testQuartz;
     2 
     3 import java.util.List;
     4 import java.util.TreeSet;
     5 
     6 /**
     7  * 任务调度线程
     8  * (1)从触发器集合中获取触发器
     9  * (2)根据获取的触发器,确认执行策略,和定时的详细信息
    10  * (3)如果符合当前执行策略,则触发器和定时详细信息配合执行定时任务
    11  * @author sxf
    12  *
    13  */
    14 public class SchedulerThread extends Thread{
    15 
    16     private Object lockObject;
    17     private boolean shutDown=false;
    18     private TreeSet<Trigger> triggerList;
    19     private List<JobDetail> jobList;
    20     
    21     public SchedulerThread(Object lockObject,TreeSet<Trigger> triggerList,List<JobDetail> joblist){
    22         this.lockObject=lockObject;
    23         this.triggerList=triggerList;
    24         this.jobList=joblist;
    25     }
    26     
    27     @Override
    28     public void run() {
    29     
    30         while(!shutDown){
    31             synchronized (lockObject) {
    32                 try {
    33                     //获取最近的触发器
    34                     final Trigger trigger=triggerList.pollFirst();//获取最近执行的作业
    35                     if(trigger==null){
    36                         lockObject.wait(100);
    37                         continue;
    38                     }
    39                     long curr=System.currentTimeMillis();
    40                     //从触发器中获取该触发器对应的执行策略
    41                     long nextTime=trigger.getNextFireTime();
    42                     while(nextTime>curr&&!shutDown){
    43                         curr=System.currentTimeMillis();
    44                         if(nextTime>curr+1){
    45                             lockObject.wait(nextTime-curr);
    46                         }
    47                         if(!shutDown){
    48                             //获取最早的定时任务在集合中的索引
    49                             int index=jobList.indexOf(new JobDetail(trigger.getJobKey(), null));
    50                             //获取最早的定时
    51                             JobDetail jobDetail=jobList.get(index);
    52                             //利用反射机制,获取定时任务的类
    53                             Job job=jobDetail.getClazz().newInstance();
    54                             //执行定时任务
    55                             job.exectute(jobDetail.getJobData());
    56                             trigger.resert();
    57                             nextTime=trigger.getNextFireTime();
    58                             if(nextTime!=-1){
    59                                 triggerList.add(trigger);
    60                             }else{
    61                                 break;
    62                             }
    63                             
    64                         }
    65                     }
    66                 } catch (Exception e) {
    67                     e.printStackTrace();
    68                 }finally{
    69                     
    70                 }
    71             }
    72         }
    73     }
    74     
    75     public void halt(){
    76         synchronized (lockObject) {
    77             shutDown=true;
    78             lockObject.notifyAll();
    79         }
    80     }
    81     
    82 }
    View Code

    【6】客户端测试类

     1 package com.yeepay.sxf.testQuartz;
     2 
     3 /**
     4  * 客户端测试
     5  * 该定时模拟,和jdk自带的TimerTask很相似。
     6  * @author sxf
     7  *
     8  */
     9 public class ClientTest {
    10 
    11     public static void main(String[] args) {
    12         final JobDetail detail1=new JobDetail("job1",Job.class);
    13         detail1.getJobData().put("type", "job1");
    14         final JobDetail detail2=new JobDetail("job2",Job.class);
    15         detail2.getJobData().put("type", "job2");
    16         final Trigger trigger1=new Trigger();
    17         trigger1.setNextFireTime(System.currentTimeMillis()+30001);
    18         final Trigger trigger2=new Trigger();
    19         trigger2.setNextFireTime(System.currentTimeMillis()+10001);
    20         
    21         Scheduler scheduler=new Scheduler();
    22         scheduler.schedulerJob(detail1, trigger1);
    23         scheduler.schedulerJob(detail2, trigger2);
    24         
    25         scheduler.start();
    26         try {
    27             Thread.sleep(100001);
    28         } catch (InterruptedException e) {
    29             // TODO Auto-generated catch block
    30             e.printStackTrace();
    31         }
    32         scheduler.halt();
    33     }
    34 }
    View Code
  • 相关阅读:
    Android:res之selector背景选择器
    工作备份 build.gradle
    Android studio听云接入另外一种方式
    自由开发者_免费可商用的图片资源推荐
    Duplicate files copied in APK META-INF/LICENSE.txt
    模仿九宫格拼音输入法,根据输入的数字键,形成对应的汉字拼音
    Map转Bean小工具
    验证身份证是否合法算法
    jqzoom插件图片放大功能的一些BUG
    外层div高度不随内层div高度改变的解决办法
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/5143100.html
Copyright © 2011-2022 走看看