動態添加定時任務-quartz定時器

Quartz動態添加、修改和刪除定時任務java

在項目中有一個需求,須要靈活配置調度任務時間,剛開始用的Java自帶的java.util.Timer類,經過調度一個java.util.TimerTask任務,雖然可以執行,可是在內部類裏不能調用service,仍是有不少不變,後來在網上查了不少資料,雖然本人級別不夠,可是經過各類組合嘗試,終於找到了方法,而後才發現竟是如此簡單,汗顏。。。下面來分享給你們。spring

  1.說明: apache

spring3.1如下的版本必須使用quartz1.x系列,3.1以上的版本才支持quartz 2.x。在quartz1.x系列中org.quartz.CronTrigger是個類,而在quartz2.x系列中org.quartz.CronTrigger變成了接口,從而形成沒法用spring的方式配置quartz的觸發器(trigger)。json

     我使用的quartz版本是2.2.1 。xcode

     最終實現的功能:ide

      1) 可添加新任務,刪除任務,更新任務,暫停任務,恢復任務 ;函數

      2) 動態添加定時任務,按時執行相應的邏輯 ;ui

 2.配置即便用spa

1)首先咱們要一個定時器管理類,這個很重要。全部的定時器操做都要用到這個類。.net


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

相關文章
相關標籤/搜索