定时组件quartz系列<一>模拟定时组件小程序

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

一、核心概念
 
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

 

相关文章
|
2月前
|
小程序 数据可视化 JavaScript
微信小程序:轻松实现时间轴组件
本文介绍了如何在微信小程序中实现一个可视化时间轴组件。该组件适用于展示用户资金流动、投资结算等时间节点,帮助用户直观了解资金去向。时间轴支持自定义节点形状、显示序号、倒序排列等功能,并通过插槽灵活定义动态内容。文中详细介绍了组件的设计与使用方法,以及如何结合动态 slot 实现自定义操作。该组件为展示用户资金信息提供了美观、易用的解决方案。
68 1
微信小程序:轻松实现时间轴组件
|
2月前
|
小程序
微信小程序动态tabBar实现:基于自定义组件,灵活支持不同用户角色与超过5个tab自由组合(更新版)
微信小程序动态tabBar实现:基于自定义组件,灵活支持不同用户角色与超过5个tab自由组合(更新版)
549 1
|
2月前
|
小程序 搜索推荐 API
微信小程序:自定义关注公众号组件样式
尽管关注公众号组件的样式固定且不可修改,但产品经理的需求却需要个性化的定制。在这种情况下,我们需要寻找解决方案,以满足这些特殊需求,尽管这可能有点棘手。
72 0
微信小程序:自定义关注公众号组件样式
|
2月前
|
小程序 前端开发 JavaScript
微信小程序图表制作利器:ECharts组件的使用与技巧
微信小程序图表制作利器:ECharts组件的使用与技巧
70 1
|
2月前
|
缓存 小程序 索引
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
224 1
|
2月前
|
小程序 JavaScript
微信小程序之input组件及其获取用户输入信息
微信小程序之input组件及其获取用户输入信息
66 1
|
3月前
|
小程序 容器
微信小程序常用组件的简单使用 view,scroll-view,swiper,swiper-item,text,rich-text,button,image
本文介绍了微信小程序中常用组件的使用方法,包括view、scroll-view、swiper与swiper-item、text与rich-text、button以及image组件。详细解释了各组件的功能、属性以及如何在小程序页面中进行使用。
微信小程序常用组件的简单使用 view,scroll-view,swiper,swiper-item,text,rich-text,button,image
|
2月前
|
小程序 前端开发 JavaScript
小程序入门之认识view和text组件
小程序入门之认识view和text组件
85 0
|
4月前
|
人工智能 小程序 编译器
Ant Design Mini 问题之Antd Mini 使用小程序函数式组件(functional-mini)来确保组件逻辑适配到双端,如何实现
Ant Design Mini 问题之Antd Mini 使用小程序函数式组件(functional-mini)来确保组件逻辑适配到双端,如何实现
|
4月前
|
小程序 前端开发 API
Ant Design Mini 问题之在微信小程序中,由于不支持slot特性,Ant Design Mini的什么组件功能受到了限制,如何解决
Ant Design Mini 问题之在微信小程序中,由于不支持slot特性,Ant Design Mini的什么组件功能受到了限制,如何解决
116 1