zoukankan      html  css  js  c++  java
  • 动态添加定时任务-quartz定时器

    Quartz动态添加、修改和删除定时任务

    在项目中有一个需求,需要灵活配置调度任务时间,刚开始用的Java自带的java.util.Timer类,通过调度一个java.util.TimerTask任务,虽然能够执行,但是在内部类里不能调用service,还是有很多不变,后来在网上查了很多资料,虽然本人级别不够,但是通过各种组合尝试,终于找到了方法,然后才发现竟是如此简单,汗颜。。。下面来分享给大家。

      1.说明: 

    spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x。在quartz1.x系列中org.quartz.CronTrigger是个类,而在quartz2.x系列中org.quartz.CronTrigger变成了接口,从而造成无法用spring的方式配置quartz的触发器(trigger)。

         我使用的quartz版本是2.2.1 。

         最终实现的功能:

          1) 可添加新任务,删除任务,更新任务,暂停任务,恢复任务 ;

          2) 动态添加定时任务,按时执行相应的逻辑 ;

     2.配置即使用

    1)首先我们要一个定时器管理类,这个很重要。所有的定时器操作都要用到这个类。

    
    import java.text.ParseException;  
    import java.text.SimpleDateFormat;  
    import java.util.Date;  
    import org.quartz.JobBuilder.newJob; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.JobDetail; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.TriggerKey; import org.quartz.impl.StdSchedulerFactory;
    /** * * @Description * @author qgw * 2016 上午10:05:59 ^_^ */ public class QuartzManager { private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory(); private static String JOB_GROUP_NAME = "MY_JOBGROUP_NAME"; private static String TRIGGER_GROUP_NAME = "MY_TRIGGERGROUP_NAME"; /** * @Description: 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名 * @param jobName 任务名 * @param cls 任务 * @param time 时间设置,参考quartz说明文档 * qgw 2016年1月21日 下午3:30:10 ^_^ */ @SuppressWarnings("unchecked") public static void addJob(String jobName, Class cls, String time,Object scheduleJob) { try { Scheduler sched = gSchedulerFactory.getScheduler(); JobDetail job = newJob(cls) .withIdentity(jobName, JOB_GROUP_NAME) .build(); // 添加具体任务方法 job.getJobDataMap().put("scheduleJob", scheduleJob); // 表达式调度构建器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(time); // 按新的cronExpression表达式构建一个新的trigger Trigger trigger = TriggerBuilder .newTrigger() .withIdentity(jobName, TRIGGER_GROUP_NAME) .withSchedule(scheduleBuilder).build(); //交给scheduler去调度 sched.scheduleJob(job, trigger); // 启动 if (!sched.isShutdown()) { sched.start(); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 添加一个定时任务 * @param jobName 任务名 * @param jobGroupName 任务组名 * @param triggerName 触发器名 * @param triggerGroupName 触发器组名 * @param jobClass 任务 * @param time 时间设置,参考quartz说明文档 * qgw 2016年1月21日 下午3:27:00 ^_^ */ @SuppressWarnings("unchecked") public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class jobClass, String time) { try { Scheduler sched = gSchedulerFactory.getScheduler(); JobDetail job = newJob(jobClass) .withIdentity(jobName, jobGroupName) .build(); // 表达式调度构建器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(time); // 按新的cronExpression表达式构建一个新的trigger Trigger trigger = TriggerBuilder .newTrigger() .withIdentity(triggerName, triggerGroupName) .withSchedule(scheduleBuilder).build(); sched.scheduleJob(job, trigger); // 启动 if (!sched.isShutdown()) { sched.start(); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名) * @param jobName * @param time * qgw 2016年1月21日 下午3:28:34 ^_^ */ @SuppressWarnings("unchecked") public static void modifyJobTime(String jobName, String time) { TriggerKey triggerKey = TriggerKey.triggerKey( jobName, TRIGGER_GROUP_NAME); try { Scheduler sched = gSchedulerFactory.getScheduler(); CronTrigger trigger =(CronTrigger) sched.getTrigger(triggerKey); if (trigger == null) { return; } String oldTime = trigger.getCronExpression(); if (!oldTime.equalsIgnoreCase(time)) { CronScheduleBuilder scheduleBuilder =CronScheduleBuilder.cronSchedule(time); //按新的cronExpression表达式重新构建trigger trigger = trigger.getTriggerBuilder().withIdentity(triggerKey) .withSchedule(scheduleBuilder).build(); //按新的trigger重新设置job执行 sched.rescheduleJob(triggerKey, trigger); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 修改一个任务的触发时间 * @param triggerName * @param triggerGroupName * @param time * @author qgw * @date 2016年1月27日 下午4:45:15 ^_^ */ public static void modifyJobTime(String triggerName, String triggerGroupName, String time) { TriggerKey triggerKey = TriggerKey.triggerKey( triggerName, triggerGroupName); try { Scheduler sched = gSchedulerFactory.getScheduler(); CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey); if (trigger == null) { return; } String oldTime = trigger.getCronExpression(); if (!oldTime.equalsIgnoreCase(time)) { // trigger已存在,则更新相应的定时设置 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder .cronSchedule(time); // 按新的cronExpression表达式重新构建trigger trigger = trigger.getTriggerBuilder().withIdentity(triggerKey) .withSchedule(scheduleBuilder).build(); // 按新的trigger重新设置job执行 sched.resumeTrigger(triggerKey); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description 移除一个任务(使用默认的任务组名,触发器名,触发器组名) * @param jobName * @author qgw * @date 2016年1月29日 下午2:21:16 ^_^ */ public static void removeJob(String jobName) { TriggerKey triggerKey = TriggerKey.triggerKey( jobName, TRIGGER_GROUP_NAME); JobKey jobKey = JobKey.jobKey(jobName, JOB_GROUP_NAME); try { Scheduler sched = gSchedulerFactory.getScheduler(); Trigger trigger = (Trigger) sched.getTrigger(triggerKey); if (trigger == null) { return; } sched.pauseTrigger(triggerKey);;// 停止触发器 sched.unscheduleJob(triggerKey);// 移除触发器 sched.deleteJob(jobKey);// 删除任务 } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 移除一个任务 * @param jobName * @param jobGroupName * @param triggerName * @param triggerGroupName * @author qgw * @date 2016年1月29日 下午2:21:16 ^_^ */ public static void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) { TriggerKey triggerKey = TriggerKey.triggerKey( jobName, triggerGroupName); JobKey jobKey = JobKey.jobKey(jobName, jobGroupName); try { Scheduler sched = gSchedulerFactory.getScheduler(); sched.pauseTrigger(triggerKey);// 停止触发器 sched.unscheduleJob(triggerKey);// 移除触发器 sched.deleteJob(jobKey);// 删除任务 } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description:暂停一个任务 * @param jobName * @param jobGroupName * qgw 2016年1月22日 下午4:24:55 ^_^ */ public static void pauseJob(String jobName, String jobGroupName) { JobKey jobKey =JobKey.jobKey(jobName, jobName); try { Scheduler sched = gSchedulerFactory.getScheduler(); sched.pauseJob(jobKey); } catch (SchedulerException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * @Description:暂停一个任务(使用默认组名) * @param jobName * @param jobGroupName * qgw 2016年1月22日 下午4:24:55 ^_^ */ public static void pauseJob(String jobName) { JobKey jobKey =JobKey.jobKey(jobName, JOB_GROUP_NAME); try { Scheduler sched = gSchedulerFactory.getScheduler(); sched.pauseJob(jobKey); } catch (SchedulerException e) { e.printStackTrace(); } } /** * @Description:启动所有定时任务 * @author qgw * @date 2016年1月29日 下午2:21:16 ^_^ */ public static void startJobs() { try { Scheduler sched = gSchedulerFactory.getScheduler(); sched.start(); } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description 关闭所有定时任务 * @author qgw * @date 2016年1月25日 下午2:26:54 ^_^ */ public static void shutdownJobs() { try { Scheduler sched = gSchedulerFactory.getScheduler(); if (!sched.isShutdown()) { sched.shutdown(); } } catch (Exception e) { throw new RuntimeException(e); } } }

      这样我们就可以通过这个类对定时任务做 添加新任务,删除任务,更新任务,暂停任务,恢复任务。另外说明一点,执行定时任务的类为传入的参数Class cls。这个类为反射出来的类,不归spring管理,所以在这个类里注入是不成功的,需要通过spring的上下文获取bean,并set到构造函数中去进行初始化。

    调用类举例:

    import java.util.ArrayList;  
    import java.util.HashMap;  
    import java.util.List;  
    import java.util.Map;  
      
    import net.sf.json.JSONObject;  
      
    import org.apache.log4j.Logger;  
    import org.quartz.DisallowConcurrentExecution;  
    import org.quartz.Job;  
    import org.quartz.JobExecutionContext;  
    import org.quartz.JobExecutionException;  
    import org.springframework.context.ApplicationContext;  
      
    /** 
     * 定时任务运行(反射出来的类) 
     * @Description 
     * @author qgw 
     * 2016 下午2:39:37 ^_^ 
     */  
    @DisallowConcurrentExecution  
    public class QuartzJobFactory implements Job {  
          
        private static final Logger log = Logger.getLogger("");  
        @Override  
        public void execute(JobExecutionContext context) throws JobExecutionException {  
              
            log.info("任务运行开始-------- start --------");   
            try {  
                //ScheduleJob任务运行时具体参数,可自定义  
                ScheduleJob scheduleJob =(ScheduleJob) context.getMergedJobDataMap().get(  
                        "scheduleJob");  
            }catch (Exception e) {  
                log.info("捕获异常==="+e);  
            }  
            log.info("任务运行结束-------- end --------");   
        }  
    }  

    2)下面就是调用了

    import java.util.HashMap;  
    import java.util.List;  
    import java.util.Map;  
      
    import net.sf.json.JSONObject;  
      
    import org.apache.log4j.Logger;  
      
    /** 
     * 加载定时任务 
     * @Description 
     * @author qgw 
     * 2016 下午2:24:58 ^_^ 
     */  
    @SuppressWarnings("unchecked")  
    public class LoadTask {  
        private static final Logger log = Logger.getLogger("");  
        /** 
         * @param sendTime 发送时间  
         * @return 
         * @author qgw  
         * @date 2016年1月26日 下午3:39:13 ^_^ 
         */  
        public static boolean timerTask(long sendTime,long msgId) {  
            String cron = QuartzManager.getQuartzTime(Util.toString(sendTime));//获得quartz时间表达式,此方法自己写  
            ScheduleJob job = new ScheduleJob();  
            String jobName = msgId+"_job";  
            job.setJobId(msgId);  
            job.setJobName(jobName);  
            job.setCreTime(nowTime);  
            job.setJobCron(cron);  
            job.setJobTime(sendTime);  
            job.setJobGroup("MY_JOBGROUP_NAME");  
            job.setJobDesc(desc);  
            try {  
                //删除已有的定时任务  
                QuartzManager.removeJob(jobName);  
                //添加定时任务  
                QuartzManager.addJob(jobName, QuartzJobFactory.class, cron,job);  
                return true;  
            } catch (Exception e) {  
                log.info("加载定时器错误:"+e);  
                return false;  
            }  
        }  
    }  

    3.注意

    由于定时任务不断添加,而且不被销毁,时间长了的话可能会有内存溢出的可能,所以最好还是添加定时任务,把每天过期的定时任务清理一下,个人建议。

    4.总结

    关于quartz定时器动态添加定时任务的各种方法,要基于项目需求去不断改进。目前此方法已投入使用,可能还有不完善的地方,希望各位大神来补充。
    5.参考

    参考文章:http://www.dexcoder.com/selfly/article/311

    文章转载至 http://blog.csdn.net/u012414587/article/details/50605861

  • 相关阅读:
    深入Android 【一】 —— 序及开篇
    Android中ContentProvider和ContentResolver使用入门
    深入Android 【六】 —— 界面构造
    The service cannot be activated because it does not support ASP.NET compatibility. ASP.NET compatibility is enabled for this application. Turn off ASP.NET compatibility mode in the web.config or add the AspNetCompatibilityRequirements attribute to the ser
    Dynamic Business代码片段总结
    对文件的BuildAction以content,resource两种方式的读取
    paraview 3.12.0 windows下编译成功 小记
    百度网盘PanDownload使用Aria2满速下载
    netdata的安装与使用
    用PS给证件照排版教程
  • 原文地址:https://www.cnblogs.com/rinack/p/7815272.html
Copyright © 2011-2022 走看看