Quartz项目实践总结

来源:互联网 发布:ntfs for mac 10.12.6 编辑:程序博客网 时间:2024/05/22 06:32

Quartz介绍

Quartz是一个开源的任务调度系统,在实际的项目开发中需要很多调度任务来完成业务。为在项目更好应用,调试我们需要了解它主要结构,及特征。

运行特征

  • 很容易集成到应用程序中,spring有很好支持。
  • 支持各种cronExpression表达式定制触发器。
  • 可以将任务持久化到数据库,并支持集群。

主要对象

  1. Job表示一个工作,要执行的具体内容。此接口中只有一个方法
    void execute(JobExecutionContext context)
  2. JobDetail JobDetail表示一个具体的可执行的调度程序,Job是这个可执行程调度程序所要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略。
  3. Trigger代表一个调度参数的配置,什么时候去调。
  4. Scheduler代表一个调度容器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合,就可以被Scheduler容器调度了。

通过如下代码例子来理解它们关系(quartz-2.2.1.jar):

public class quartzTest {  public static void main(String[] args) {    // TODO Auto-generated method stub    try {      // 3、创建Scheduler对象,并配置JobDetail和Trigger对象      DirectSchedulerFactory schedulerFactory = DirectSchedulerFactory.getInstance();      schedulerFactory.createVolatileScheduler(2);      Scheduler scheduler = schedulerFactory.getScheduler();      buildScheduler(scheduler);      // 开启容器      scheduler.start();      // 查询容器中job      showJobTask(scheduler);    } catch (Exception e) {      e.printStackTrace();    }  }  public static void showJobTask(Scheduler scheduler) throws SchedulerException {    List<String> jobGroupNames = scheduler.getJobGroupNames();    for (String jobGroupName : jobGroupNames) {      // scheduler.get      Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupEquals(jobGroupName));      for (JobKey jobKey : jobKeys) {        JobDetail JobDetail = scheduler.getJobDetail(jobKey);        System.out.println(JobDetail.getDescription() + "cccc" + jobKeys.toString());      }    }  }  public static void buildScheduler(Scheduler scheduler) throws SchedulerException {    // 创建一个JobDetail    JobDetail jobDetail = new JobDetailImpl("andreTaskName", "group1", TestTask.class);    // 创建一个Trigger触发器    SimpleTriggerImpl trigger = new SimpleTriggerImpl();    trigger.setJobGroup("jobGroup");    trigger.setName("trigger_one");    trigger.setStartTime(new Date());    // trigger.setEndTime(endTime);    // 设置重复间隔时间 2s    trigger.setRepeatInterval(2000L);    trigger.setRepeatCount(3);    // 添加到相应的scheduler容器中    scheduler.scheduleJob(jobDetail, trigger);  }  /**   * 具体job任务   *    * @author my   * @Date 2016年7月14日 下午3:47:57   */  public static class TestTask implements Job {    @Override    public void execute(JobExecutionContext context) throws JobExecutionException {      // TODO Auto-generated method stub      System.out.println("System executing something." + new Date());    }  }}

总结

  1. scheduler是一个计划调度器容器(总部),容器里面可以盛放众多的JobDetail和trigger,当容器启动后,里面的每个JobDetail都会根据trigger按部就班自动去执行。
  2. JobDetail是一个可执行的工作,它本身可能是有状态的。对应数据表qrtz_job_details
  3. Trigger代表一个调度参数的配置,什么时候去调。qrtz_cron_triggers(主要cron表达式信息),qrtz_triggers(存储了prev_fire_time,trigger_state,next_fire_time等触发要素).
  4. scheduler是个容器,容器中有一个线程池,用来并行调度执行每个作业,这样可以提高容器效率。
  5. 清理某任务sql顺序:
----删除顺序应该这样,只有对cron_expression ,zone_id表达式记录。DELETE FROM   qrtz_cron_triggers WHERE trigger_name="snapshotAnalyzeSchedulerTriggerBean2";DELETE FROM qrtz_triggers WHERE trigger_name="snapshotAnalyzeSchedulerTriggerBean2";--只描述了具体jobDELETE FROM qrtz_job_details  WHERE job_name="snapshotAnalyzeSchedulerJobDetail";

集群原理

一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。

图:表示了每个节点直接与数据库通信,若离开数据库将对其他节点一无所知

image

动态修改job

Quartz支持在scheduler.start();后动态addJob,ModifyJobTime,removeJob,pauseJob(停止任务),executeJob(立即执行任务)等。大家可以通过阅读代码来理解。

package com.calm.b.common.quartz;import javax.annotation.Resource;import org.quartz.CronTrigger;import org.quartz.JobDataMap;import org.quartz.JobKey;import org.quartz.Scheduler;import org.quartz.SchedulerFactory;import org.quartz.impl.StdScheduler;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Service;/** * 定时任务调试引擎,负责完成定时任务的执行、启动、停止。。。 */@Service("scheduleJobEngine")public class ScheduleJobEngine {  protected static Logger log = LoggerFactory.getLogger(ScheduleJobEngine.class);  private static SchedulerFactory schedulerFactory = null;  private static String JOB_GROUP_NAME = "DEFAULT";  private static String TRIGGER_GROUP_NAME = "TRIGGERGROUP_NAME";  /**   * 注入的spring Scheduler容器bean   */  @Resource  private StdScheduler quartzScheduler;  /**   * 增加任务   *    * @param jobName   * @param jobClass   * @param expression   */  public static void addJob(String jobName, String jobClass, String expression) {    addJob(jobName, JOB_GROUP_NAME, jobName, TRIGGER_GROUP_NAME, jobClass, expression);  }  public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName,      String jobClass, String expression) {    log.debug("addJob:" + jobName);    try {      Scheduler scheduler = schedulerFactory.getScheduler();      // JobDetail jobDetail = new JobDetail(jobName, jobGroupName, Class.forName(jobClass));//      // 任务名,任务组,任务执行类      // // 触发器      // CronTrigger trigger = new CronTrigger(triggerName, triggerGroupName);// 触发器名,触发器组      // trigger.setCronExpression(expression);// 触发器时间设定      // scheduler.scheduleJob(jobDetail, trigger);      // 启动      if (!scheduler.isShutdown()) {        scheduler.start();      }    } catch (Exception e) {      log.error(e.getMessage(), e);    }  }  /**   * 修改任务执行时间   *    * @param triggerName   * @param expression   */  public static void modifyJobTime(String triggerName, String expression) {    modifyJobTime(triggerName, TRIGGER_GROUP_NAME, expression);  }  public static void modifyJobTime(String triggerName, String triggerGroupName, String expression) {    log.debug("modifyJobTime:" + triggerName);    try {      Scheduler scheduler = schedulerFactory.getScheduler();      CronTrigger trigger = null;      // = (CronTrigger) scheduler.getTrigger(triggerName, triggerGroupName);      if (trigger == null) {        return;      }      String oldTime = trigger.getCronExpression();      if (!oldTime.equalsIgnoreCase(expression)) {        CronTrigger ct = (CronTrigger) trigger;        // 修改时间        // ct.setCronExpression(expression);        // 重启触发器        // scheduler.resumeTrigger(triggerName, triggerGroupName);      }    } catch (Exception e) {      log.error(e.getMessage(), e);    }  }  /**   * 移除任务   *    * @param jobName   */  public static void removeJob(String jobName) {    removeJob(jobName, JOB_GROUP_NAME, jobName, TRIGGER_GROUP_NAME);  }  public static void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {    log.debug("removeJob:" + jobName);    try {      // Scheduler scheduler = schedulerFactory.getScheduler();      // scheduler.pauseTrigger(triggerName, triggerGroupName);// 停止触发器      // scheduler.unscheduleJob(triggerName, triggerGroupName);// 移除触发器      // scheduler.deleteJob(jobName, jobGroupName);// 删除任务    } catch (Exception e) {      log.error(e.getMessage(), e);    }  }  /**   * 停止任务   *    * @param jobName   */  public void pauseJob(String jobName) {    pauseJob(jobName, JOB_GROUP_NAME);  }  public void pauseJob(String jobName, String jobGroupName) {    log.debug("pauseJob:" + jobName);    try {      quartzScheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));    } catch (Exception e) {      log.error(e.getMessage(), e);    }  }  /**   * 立即执行任务   *    * @param jobNam   * @param dataMap   */  public void execJob(String jobName, JobDataMap dataMap) {    execJob(jobName, JOB_GROUP_NAME, dataMap);  }  public void execJob(String jobName) {    execJob(jobName, JOB_GROUP_NAME, new JobDataMap());  }  public void execJob(String jobName, String jobGroupName, JobDataMap dataMap) {    log.debug("execJob:" + jobName);    try {      quartzScheduler.triggerJob(JobKey.jobKey(jobName, jobGroupName), dataMap);    } catch (Exception e) {      log.error(e.getMessage(), e);    }  }  /**   * 恢复任务   *    * @param jobName   */  public void resumeJob(String jobName) {    resumeJob(jobName, JOB_GROUP_NAME);  }  public void resumeJob(String jobName, String jobGroupName) {    log.debug("resumeJob:" + jobName);    try {      quartzScheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));    } catch (Exception e) {      log.error(e.getMessage(), e);    }  }  /**   * 启动所有定时任务   */  public void startJobs() {    log.debug("startJobs");    try {      if (quartzScheduler.isShutdown()) {        quartzScheduler.start();      }    } catch (Exception e) {      log.error(e.getMessage(), e);    }  }  /**   * 关闭所有定时任务   */  public void shutdownJobs() {    log.debug("shutdownJobs");    try {      if (!quartzScheduler.isShutdown()) {        quartzScheduler.shutdown();      }      // quartzScheduler.    } catch (Exception e) {      log.error(e.getMessage(), e);    }  }}

参考文档

  1. 配置corn参考:http://www.cnblogs.com/skyblue/p/3296350.html
  2. 集群设置及原理参考:
    http://sundoctor.iteye.com/blog/486055
    http://blog.csdn.net/zxl315/article/details/10830105

  3. QuartzSchedulerThread核心代码:
    http://blog.csdn.net/cutesource/article/details/4965520

0 0