任务调度开源框架Quartz动态添加、修改和删除定时任务

Quartz 是个开源的作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。Quartz框架包含了调度器监听、作业和触发器监听。你可以配置作业和触发器监听为全局监听或者是特定于作业和触发器的监听。Quartz 允许开发人员根据时间间隔(或天)来调度作业。它实现了作业和触发器的多对多关系,还能把多个作业与不同的触发器关联。整合了 Quartz 的应用程序可以重用来自不同事件的作业,还可以为一个事件组合多个作业。并且还能和spring配置整合使用。Quartz在功能上远远超越了JDK自带的Timer,很好很强大!好啦,直接上代码:

package com.zoki.module.timer;
import ch.qos.logback.classic.Logger;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.LoggerFactory;
/**
 * 定时器任务调度管理器
 *
 * @author zhoukai
 */
public class QuartzManager {
    private final String jobGroupName;
    private final String triggerGroupName;
    private Scheduler sched;
    private final static SchedulerFactory sf = new StdSchedulerFactory();
    private final static Map<String, QuartzManager> instanceMap = new ConcurrentHashMap<>();
    private final static Logger logger = (Logger) LoggerFactory.getLogger(QuartzManager.class);
    /**
     * 构造方法,外部不能实例化
     *
     * @param jobGroupName 工作组名
     * @param triggerGroupName 触发器组名
     */
    private QuartzManager(String jobGroupName, String triggerGroupName) {
        this.jobGroupName = jobGroupName;
        this.triggerGroupName = triggerGroupName;
    }
    /**
     * 获取调度器
     *
     * @return 定时调度器
     * @throws SchedulerException 调度器内部执行异常
     */
    private Scheduler getScheduler() throws SchedulerException {
        if (sched == null) {
            sched = sf.getScheduler();
            //sched.getListenerManager().addTriggerListener(new QuartzTriggerListener());
            //sched.getListenerManager().addSchedulerListener(new QuartzSchedulerListener(sched));
        }
        return sched;
    }
    /**
     * 获取一个定时调度管理器
     *
     * @param jobGroupName 工作组名
     * @param triggerGroupName 触发器组名
     * @return 定时调度管理器
     */
    public static QuartzManager getInstance(String jobGroupName, String triggerGroupName) {
        String instanceKey = jobGroupName + "_" + triggerGroupName;
        if (instanceMap.containsKey(instanceKey)) {
            return instanceMap.get(instanceKey);
        }
        QuartzManager manager = new QuartzManager(jobGroupName, triggerGroupName);
        instanceMap.put(instanceKey, manager);
        return manager;
    }
    /**
     * 获取一个定时调度管理器
     *
     * @param groupName 工作组名和触发器组名相同
     * @return 定时调度管理器
     */
    public static QuartzManager getInstance(String groupName) {
        return getInstance(groupName, groupName);
    }
    /**
     * 关闭调度器
     *
     * @param waitForJobsToComplete 是否等候所有工作被调度完成后再关闭
     */
    public void shutdown(boolean waitForJobsToComplete) {
        String instanceKey = jobGroupName + "_" + triggerGroupName;
        if (instanceMap.containsKey(instanceKey)) {
            QuartzManager manager = instanceMap.get(instanceKey);
            if (manager != null && manager.sched != null) {
                try {
                    manager.sched.shutdown(waitForJobsToComplete);
                } catch (SchedulerException ex) {
                    logger.debug(ex.getLocalizedMessage(), ex);
                }
            }
        }
    }
    /**
     * 关闭调度器
     */
    public void shutdown() {
        shutdown(false);
    }
    
    /**
     * 添加一个调度任务
     *
     * @param jobName 任务名
     * @param cls 任务类型
     * @param start 任务执行的开始时间,null表示立刻执行
     * @param end 任务执行的结束时间,null表示任务在执行repeat次数后自动结束
     * @param jobBindData 绑定到job中的数据,可为null
     * @param intervalType 任务执行时间间隔类型,1、毫秒,2、秒,3、分,4、小时,默认为2
     * @param intervalValue 任务执行时间间隔
     * @param repeat 任务执行次数,0表示执行一次,实际执行次数为此值+1
     * @throws SchedulerException
     */
    public void addJob(String jobName, Class cls, Date start, Date end, Map<String, Object> jobBindData, int intervalType, long intervalValue, int repeat) throws SchedulerException {
        JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, jobGroupName).build();
        if (jobBindData != null) {
            for (Entry<String, Object> entry : jobBindData.entrySet()) {
                jobDetail.getJobDataMap().put(entry.getKey(), entry.getValue());
            }
        }
        SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
        switch (intervalType) {
            case 1:
                //毫秒
                simpleScheduleBuilder.withIntervalInMilliseconds(intervalValue);
                break;
            case 3:
                //分
                simpleScheduleBuilder.withIntervalInMinutes((int) intervalValue);
                break;
            case 4:
                //时
                simpleScheduleBuilder.withIntervalInHours((int) intervalValue);
                break;
            default:
                //秒
                simpleScheduleBuilder.withIntervalInSeconds((int) intervalValue);
                break;
        }
        if(repeat >= 0) {
            simpleScheduleBuilder.withRepeatCount(repeat);
        }
        TriggerBuilder<Trigger> builder = TriggerBuilder.newTrigger()
                .withIdentity(jobName, triggerGroupName);
        if (start == null) {
            builder.startNow();
        } else {
            builder.startAt(start);
        }
        if (end != null) {
            builder.endAt(end);
        }
        Trigger trigger = builder.withSchedule(simpleScheduleBuilder).build();
        Scheduler scheduler = getScheduler();
        scheduler.scheduleJob(jobDetail, trigger);
        if (!scheduler.isShutdown()) {
            scheduler.start();
        }
    }
    
    /**
     * 添加一个调度任务,在start时间执行一次
     * @param jobName 任务名
     * @param cls 任务类型
     * @param start 任务执行的开始时间,null表示立刻执行
     * @param end 任务执行的结束时间,null表示任务在执行repeat次数后自动结束
     * @param jobBindData 绑定到job中的数据,可为null
     * @throws SchedulerException
     */
    public void addJob(String jobName, Class cls, Date start , Date end, Map<String, Object> jobBindData) throws SchedulerException {
        this.addJob(jobName, cls, start, end, jobBindData, 2, 1, 0);
    }
    
    /**
     * 添加一个调度任务,在start时间执行一次
     * @param jobName 任务名
     * @param cls 任务类型
     * @param start 任务执行的开始时间,null表示立刻执行
     * @param jobBindData 绑定到job中的数据,可为null
     * @throws SchedulerException
     */
    public void addJob(String jobName, Class cls, Date start, Map<String, Object> jobBindData) throws SchedulerException {
        this.addJob(jobName, cls, start, null, jobBindData);
    }
    /**
     * 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
     *
     * @param jobName 任务名
     * @param cls
     * @param time 时间设置,参考quartz说明文档
     * @throws SchedulerException 调度器内部执行异常
     */
    public void addJob(String jobName, Class cls, String time) throws SchedulerException {
        JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, jobGroupName).build();
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(jobName, triggerGroupName)//触发器名,触发器组
                .withSchedule(CronScheduleBuilder.cronSchedule(time))
                .build();
        Scheduler scheduler = getScheduler();
        scheduler.scheduleJob(jobDetail, trigger);
        if (!scheduler.isShutdown()) {
            scheduler.start();
        }
    }
    /**
     * 移除一个任务
     *
     * @param triggerKey 触发器键
     * @param jobKey 工作任务键
     * @throws SchedulerException 调度器内部执行异常
     */
    public void removeJob(TriggerKey triggerKey, JobKey jobKey) throws SchedulerException {
        Scheduler scheduler = getScheduler();
        scheduler.pauseTrigger(triggerKey);
        scheduler.unscheduleJob(triggerKey);
        scheduler.deleteJob(jobKey);
    }
    /**
     * 移除一个任务(使用默认的任务组名,触发器名,触发器组名)
     *
     * @param jobName 工作任务名
     * @throws SchedulerException 调度器内部执行异常
     */
    public void removeJob(String jobName) throws SchedulerException {
        TriggerKey triggerKey = new TriggerKey(jobName, triggerGroupName);
        JobKey jobKey = new JobKey(jobName, jobGroupName);
        removeJob(triggerKey, jobKey);
    }
}

[java] view plain copy

在CODE上查看代码片
  1. /**
  2.  * @Description: 
  3.  *
  4.  * @Title: QuartzManager.java
  5.  * @Package com.joyce.quartz
  6.  * @Copyright: Copyright (c) 2014
  7.  *
  8.  * @author Comsys-LZP
  9.  * @date 2014-6-26 下午03:15:52
  10.  * @version V2.0
  11.  */
  12. package com.joyce.quartz;
  13. import org.quartz.CronTrigger;
  14. import org.quartz.JobDetail;
  15. import org.quartz.Scheduler;
  16. import org.quartz.SchedulerFactory;
  17. import org.quartz.impl.StdSchedulerFactory;
  18. /**
  19.  * @Description: 定时任务管理类
  20.  * 
  21.  * @ClassName: QuartzManager
  22.  * @Copyright: Copyright (c) 2014
  23.  * 
  24.  * @author Comsys-LZP
  25.  * @date 2014-6-26 下午03:15:52
  26.  * @version V2.0
  27.  */
  28. public class QuartzManager {
  29.     private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();
  30.     private static String JOB_GROUP_NAME = “EXTJWEB_JOBGROUP_NAME”;
  31.     private static String TRIGGER_GROUP_NAME = “EXTJWEB_TRIGGERGROUP_NAME”;
  32.     /**
  33.      * @Description: 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
  34.      * 
  35.      * @param jobName
  36.      *            任务名
  37.      * @param cls
  38.      *            任务
  39.      * @param time
  40.      *            时间设置,参考quartz说明文档
  41.      * 
  42.      * @Title: QuartzManager.java
  43.      * @Copyright: Copyright (c) 2014
  44.      * 
  45.      * @author Comsys-LZP
  46.      * @date 2014-6-26 下午03:47:44
  47.      * @version V2.0
  48.      */
  49.     @SuppressWarnings(“unchecked”)
  50.     public static void addJob(String jobName, Class cls, String time) {
  51.         try {
  52.             Scheduler sched = gSchedulerFactory.getScheduler();
  53.             JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, cls);// 任务名,任务组,任务执行类
  54.             // 触发器
  55.             CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);// 触发器名,触发器组
  56.             trigger.setCronExpression(time);// 触发器时间设定
  57.             sched.scheduleJob(jobDetail, trigger);
  58.             // 启动
  59.             if (!sched.isShutdown()) {
  60.                 sched.start();
  61.             }
  62.         } catch (Exception e) {
  63.             throw new RuntimeException(e);
  64.         }
  65.     }
  66.     /**
  67.      * @Description: 添加一个定时任务
  68.      * 
  69.      * @param jobName
  70.      *            任务名
  71.      * @param jobGroupName
  72.      *            任务组名
  73.      * @param triggerName
  74.      *            触发器名
  75.      * @param triggerGroupName
  76.      *            触发器组名
  77.      * @param jobClass
  78.      *            任务
  79.      * @param time
  80.      *            时间设置,参考quartz说明文档
  81.      * 
  82.      * @Title: QuartzManager.java
  83.      * @Copyright: Copyright (c) 2014
  84.      * 
  85.      * @author Comsys-LZP
  86.      * @date 2014-6-26 下午03:48:15
  87.      * @version V2.0
  88.      */
  89.     @SuppressWarnings(“unchecked”)
  90.     public static void addJob(String jobName, String jobGroupName,
  91.             String triggerName, String triggerGroupName, Class jobClass,
  92.             String time) {
  93.         try {
  94.             Scheduler sched = gSchedulerFactory.getScheduler();
  95.             JobDetail jobDetail = new JobDetail(jobName, jobGroupName, jobClass);// 任务名,任务组,任务执行类
  96.             // 触发器
  97.             CronTrigger trigger = new CronTrigger(triggerName, triggerGroupName);// 触发器名,触发器组
  98.             trigger.setCronExpression(time);// 触发器时间设定
  99.             sched.scheduleJob(jobDetail, trigger);
  100.         } catch (Exception e) {
  101.             throw new RuntimeException(e);
  102.         }
  103.     }
  104.     /**
  105.      * @Description: 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名)
  106.      * 
  107.      * @param jobName
  108.      * @param time
  109.      * 
  110.      * @Title: QuartzManager.java
  111.      * @Copyright: Copyright (c) 2014
  112.      * 
  113.      * @author Comsys-LZP
  114.      * @date 2014-6-26 下午03:49:21
  115.      * @version V2.0
  116.      */
  117.     @SuppressWarnings(“unchecked”)
  118.     public static void modifyJobTime(String jobName, String time) {
  119.         try {
  120.             Scheduler sched = gSchedulerFactory.getScheduler();
  121.             CronTrigger trigger = (CronTrigger) sched.getTrigger(jobName,TRIGGER_GROUP_NAME);
  122.             if (trigger == null) {
  123.                 return;
  124.             }
  125.             String oldTime = trigger.getCronExpression();
  126.             if (!oldTime.equalsIgnoreCase(time)) {
  127.                 JobDetail jobDetail = sched.getJobDetail(jobName,JOB_GROUP_NAME);
  128.                 Class objJobClass = jobDetail.getJobClass();
  129.                 removeJob(jobName);
  130.                 addJob(jobName, objJobClass, time);
  131.             }
  132.         } catch (Exception e) {
  133.             throw new RuntimeException(e);
  134.         }
  135.     }
  136.     /**
  137.      * @Description: 修改一个任务的触发时间
  138.      * 
  139.      * @param triggerName
  140.      * @param triggerGroupName
  141.      * @param time
  142.      * 
  143.      * @Title: QuartzManager.java
  144.      * @Copyright: Copyright (c) 2014
  145.      * 
  146.      * @author Comsys-LZP
  147.      * @date 2014-6-26 下午03:49:37
  148.      * @version V2.0
  149.      */
  150.     public static void modifyJobTime(String triggerName,
  151.             String triggerGroupName, String time) {
  152.         try {
  153.             Scheduler sched = gSchedulerFactory.getScheduler();
  154.             CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerName,triggerGroupName);
  155.             if (trigger == null) {
  156.                 return;
  157.             }
  158.             String oldTime = trigger.getCronExpression();
  159.             if (!oldTime.equalsIgnoreCase(time)) {
  160.                 CronTrigger ct = (CronTrigger) trigger;
  161.                 // 修改时间
  162.                 ct.setCronExpression(time);
  163.                 // 重启触发器
  164.                 sched.resumeTrigger(triggerName, triggerGroupName);
  165.             }
  166.         } catch (Exception e) {
  167.             throw new RuntimeException(e);
  168.         }
  169.     }
  170.     /**
  171.      * @Description: 移除一个任务(使用默认的任务组名,触发器名,触发器组名)
  172.      * 
  173.      * @param jobName
  174.      * 
  175.      * @Title: QuartzManager.java
  176.      * @Copyright: Copyright (c) 2014
  177.      * 
  178.      * @author Comsys-LZP
  179.      * @date 2014-6-26 下午03:49:51
  180.      * @version V2.0
  181.      */
  182.     public static void removeJob(String jobName) {
  183.         try {
  184.             Scheduler sched = gSchedulerFactory.getScheduler();
  185.             sched.pauseTrigger(jobName, TRIGGER_GROUP_NAME);// 停止触发器
  186.             sched.unscheduleJob(jobName, TRIGGER_GROUP_NAME);// 移除触发器
  187.             sched.deleteJob(jobName, JOB_GROUP_NAME);// 删除任务
  188.         } catch (Exception e) {
  189.             throw new RuntimeException(e);
  190.         }
  191.     }
  192.     /**
  193.      * @Description: 移除一个任务
  194.      * 
  195.      * @param jobName
  196.      * @param jobGroupName
  197.      * @param triggerName
  198.      * @param triggerGroupName
  199.      * 
  200.      * @Title: QuartzManager.java
  201.      * @Copyright: Copyright (c) 2014
  202.      * 
  203.      * @author Comsys-LZP
  204.      * @date 2014-6-26 下午03:50:01
  205.      * @version V2.0
  206.      */
  207.     public static void removeJob(String jobName, String jobGroupName,
  208.             String triggerName, String triggerGroupName) {
  209.         try {
  210.             Scheduler sched = gSchedulerFactory.getScheduler();
  211.             sched.pauseTrigger(triggerName, triggerGroupName);// 停止触发器
  212.             sched.unscheduleJob(triggerName, triggerGroupName);// 移除触发器
  213.             sched.deleteJob(jobName, jobGroupName);// 删除任务
  214.         } catch (Exception e) {
  215.             throw new RuntimeException(e);
  216.         }
  217.     }
  218.     /**
  219.      * @Description:启动所有定时任务
  220.      * 
  221.      * 
  222.      * @Title: QuartzManager.java
  223.      * @Copyright: Copyright (c) 2014
  224.      * 
  225.      * @author Comsys-LZP
  226.      * @date 2014-6-26 下午03:50:18
  227.      * @version V2.0
  228.      */
  229.     public static void startJobs() {
  230.         try {
  231.             Scheduler sched = gSchedulerFactory.getScheduler();
  232.             sched.start();
  233.         } catch (Exception e) {
  234.             throw new RuntimeException(e);
  235.         }
  236.     }
  237.     /**
  238.      * @Description:关闭所有定时任务
  239.      * 
  240.      * 
  241.      * @Title: QuartzManager.java
  242.      * @Copyright: Copyright (c) 2014
  243.      * 
  244.      * @author Comsys-LZP
  245.      * @date 2014-6-26 下午03:50:26
  246.      * @version V2.0
  247.      */
  248.     public static void shutdownJobs() {
  249.         try {
  250.             Scheduler sched = gSchedulerFactory.getScheduler();
  251.             if (!sched.isShutdown()) {
  252.                 sched.shutdown();
  253.             }
  254.         } catch (Exception e) {
  255.             throw new RuntimeException(e);
  256.         }
  257.     }
  258. }

以上就是quartz任务调度对于任务的常用操作,封装起来以便在外部调用!这样我们就需要任务的执行了:

[java] view plain copy

在CODE上查看代码片
  1. /**
  2.  * @Description: 
  3.  *
  4.  * @Title: QuartzJob.java
  5.  * @Package com.joyce.quartz
  6.  * @Copyright: Copyright (c) 2014
  7.  *
  8.  * @author Comsys-LZP
  9.  * @date 2014-6-26 下午03:37:11
  10.  * @version V2.0
  11.  */
  12. package com.joyce.quartz;
  13. import java.text.SimpleDateFormat;
  14. import java.util.Date;
  15. import org.quartz.Job;
  16. import org.quartz.JobExecutionContext;
  17. import org.quartz.JobExecutionException;
  18. /**
  19.  * @Description: 任务执行类
  20.  *
  21.  * @ClassName: QuartzJob
  22.  * @Copyright: Copyright (c) 2014
  23.  *
  24.  * @author Comsys-LZP
  25.  * @date 2014-6-26 下午03:37:11
  26.  * @version V2.0
  27.  */
  28. public class QuartzJob implements Job {
  29.     @Override
  30.     public void execute(JobExecutionContext arg0) throws JobExecutionException {
  31.         System.out.println(new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”).format(new Date())+ “★★★★★★★★★★★”);
  32.     }
  33. }

Ok,我们来测试一下:

[java] view plain copy

在CODE上查看代码片派生到我的代码片

  1. /**
  2.  * @Description: 
  3.  *
  4.  * @Title: QuartzTest.java
  5.  * @Package com.joyce.quartz.main
  6.  * @Copyright: Copyright (c) 2014
  7.  *
  8.  * @author Comsys-LZP
  9.  * @date 2014-6-26 下午03:35:05
  10.  * @version V2.0
  11.  */
  12. package com.joyce.quartz.main;
  13. import com.joyce.quartz.QuartzJob;
  14. import com.joyce.quartz.QuartzManager;
  15. /**
  16.  * @Description: 测试类
  17.  *
  18.  * @ClassName: QuartzTest
  19.  * @Copyright: Copyright (c) 2014
  20.  *
  21.  * @author Comsys-LZP
  22.  * @date 2014-6-26 下午03:35:05
  23.  * @version V2.0
  24.  */
  25. public class QuartzTest {
  26.     public static void main(String[] args) {
  27.         try {
  28.             String job_name = “动态任务调度”;
  29.             System.out.println(“【系统启动】开始(每1秒输出一次)…”);
  30.             QuartzManager.addJob(job_name, QuartzJob.class“0/1 * * * * ?”);
  31.             Thread.sleep(5000);
  32.             System.out.println(“【修改时间】开始(每2秒输出一次)…”);
  33.             QuartzManager.modifyJobTime(job_name, “10/2 * * * * ?”);
  34.             Thread.sleep(6000);
  35.             System.out.println(“【移除定时】开始…”);
  36.             QuartzManager.removeJob(job_name);
  37.             System.out.println(“【移除定时】成功”);
  38.             System.out.println(“【再次添加定时任务】开始(每10秒输出一次)…”);
  39.             QuartzManager.addJob(job_name, QuartzJob.class“*/10 * * * * ?”);
  40.             Thread.sleep(60000);
  41.             System.out.println(“【移除定时】开始…”);
  42.             QuartzManager.removeJob(job_name);
  43.             System.out.println(“【移除定时】成功”);
  44.         } catch (Exception e) {
  45.             e.printStackTrace();
  46.         }
  47.     }
  48. }

运行一下,看看效果图: