Quartz 开源任务调度框架的使用

一、目的

之前用到任务调度的内容比较少,即使有也功能相对比较简单,目前我们所用的为JDK自带的任务调度机制,功能单一,只适合短期的、简单任务调度。在Timer中所有TimeTask都在同一背景线程中运行,长时间运行全严重影响到Timer的调度工作。所以要谨慎运行jdk timer。

Quartz是开源任务调度框架中的翘首,它提供了强大的任务调度机制。Quartz 允许开发人员灵活定义触发器时间,并可对触发器和任务进行关联映射。此外Quartz提供了调度任务运行环境的持久化机制,可以保存恢复调度现场,即使系统因故障关闭,任务调度现场数据并不会丢失。Quartz 还提供了组件式侦听器、线程池等功能,可以满足开发需要的各种任务调度功能。

二 、入门

要开始使用 Quartz,需要用 Quartz API 对项目进行配置。步骤如下:

1. 下载 Quartz API。

解压缩并把 quartz-all-x.x.x.jar 放在项目文件夹内,或者把文件放在项目的类路径中。

2. 把 lib 文件夹中的 jar 文件放在项目的文件夹或项目的类路径中。

3. 如果使用 JDBCJobStore,把所有的 JDBC jar 文件放在项目的文件夹或项目的类路径中。

三、作业与任务调度

3.1 作业

通过实现 org.quartz.job 接口,可以使 Java 类变成可执行的。下面示例提供了 Quartz 作业的一个示例。这个类用一条非常简单的输出语句覆盖了 execute(JobExecutionContext context) 方法。

示例如下:

import java.util.Map;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;

import com.jiucool.sample.cronjobService;

/**
 * 
 * @author jiucool.org
 * @since 2012-7-21下午12:16:22
 */
public class MyJob implements Job {
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
	 */
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		Map dataMap = context.getJobDetail().getJobDataMap();
		ApplicationContext ctx = (ApplicationContext) dataMap.get("applicationContext");
		cronjobService jobService = (cronjobService) ctx.getBean("cronjobService";);
		jobService.startUnionPayReconciliation();
	}
}

3.2 、触发器

触发器可以实现对任务执行的调度。Quartz 提供了几种不同的触发器,复杂程度各不相同。

3.2.1 简单触发器

它只能用于指定任务在一个特定时间内运行,可指定任务的重复(时间,次数)与间隔(时间,次数)。功能类似于JDK timer. 但提供多线程线程池等功能,不会出现性能上的问题。

代码示例:

package org.quartz.examples.example1;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;

/**
 * This Example will demonstrate how to start and shutdown the Quartz 
 * scheduler and how to schedule a job to run in Quartz.
 * 
 * @author Bill Kratzer
 */
public class SimpleExample {

    
    public void run() throws Exception {
        Logger log = LoggerFactory.getLogger(SimpleExample.class);

        log.info("------- 初始化 ----------------------");

        
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();

        log.info("------- 初始化完成 -----------");

        log.info("------- 计划任务 -------------------");

        
        Date runTime = DateUtils.parse("2012-11-15 12:23:22");

        // define the job and tie it to our HelloJob class
        JobDetail job = new JobDetail("job1", "group1", HelloJob.class);
        
        // Trigger the job to run on the next round minute
        SimpleTrigger trigger = 
            new SimpleTrigger("trigger1", "group1", runTime);
        
        // Tell quartz to schedule the job using our trigger
        sched.scheduleJob(job, trigger);
        log.info(job.getFullName() + " will run at: " + runTime);  

        
        sched.start();
        log.info("------- Started Scheduler -----------------");

        // shut down the scheduler
        log.info("------- Shutting Down ---------------------");
        sched.shutdown(true);
        log.info("------- Shutdown Complete -----------------");
    }

   
}

3.2.2 Cron 触发器

CronTrigger 支持比 SimpleTrigger 更具体的调度,而且也不是很复杂。基于 cron 表达式,CronTrigger 支持类似日历的重复间隔,而不是单一的时间间隔 —— 这相对 SimpleTrigger 而言是一大改进。

Cron 表达式包括以下 7 个字段:

  • 小时
  • 月内日期
  • 周内日期
  • 年(可选字段)

特殊字符:

Cron 触发器利用一系列特殊字符,如下所示:

  • 反斜线(/)字符表示增量值。例如,在秒字段中“5/15”代表从第 5 秒开始,每 15 秒一次。
  • 问号(?)字符和字母 L 字符只有在月内日期和周内日期字段中可用。问号表示这个字段不包含具体值。所以,如果指定月内日期,可以在周内日期字段中插入“?”,表示周内日期值无关紧要。字母 L 字符是 last 的缩写。放在月内日期字段中,表示安排在当月最后一天执行。在周内日期字段中,如果“L”单独存在,就等于“7”,否则代表当月内周内日期的最后一个实例。所以“0L”表示安排在当月的最后一个星期日执行。
  • 在月内日期字段中的字母(W)字符把执行安排在最靠近指定值的工作日。把“1W”放在月内日期字段中,表示把执行安排在当月的第一个工作日内。
  • 井号(#)字符为给定月份指定具体的工作日实例。把“MON#2”放在周内日期字段中,表示把任务安排在当月的第二个星期一。
  • 星号(*)字符是通配字符,表示该字段可以接受任何可能的值。

示例:

/**
 * 
 * @author jiucool.org
 * @since 2012-7-21下午1:46:19
 */
@Log4j
public final class ScheduleForUnioPayReconciliationUtils {
	private static SchedulerFactory sf = new StdSchedulerFactory();
	private static Scheduler sched;

	private ScheduleForUnioPayReconciliationUtils() {
	}

	/**
	 * 开始计划
	 * 
	 * @author jiucool.org
	 * @throws Exception
	 * @since 2012-7-21下午1:47:13
	 */
	public static void startSche() throws Exception {
		sched = sf.getScheduler();
		// job 1 will run every 20 seconds
		JobDetail job = JobBuilder.newJob(UnionPayReconciliationJob.class).withIdentity("job1", "group1").build();
		CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(CronScheduleBuilder.cronSchedule("0 0 0   * *  ?"))
				.build();
		Date ft = sched.scheduleJob(job, trigger);
		log.info(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: " + trigger.getCronExpression());
		
		sched.start();
		log.info("------- Started Scheduler -----------------");
	}

	/**
	 * 关闭计划 
	 * @author jiucool.org
	 * @throws Exception
	 * @since 2012-7-21下午1:50:52
	 */
	public static void shutDown() throws Exception {
		if (sched != null) {
			log.info("------- Shutting Down ---------------------");
			sched.shutdown(true);
			log.info("------- Shutdown Complete -----------------");
			SchedulerMetaData metaData = sched.getMetaData();
			log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
		}
	}
}

四 、Quartz 与Spring 整合

4.1 quartz 与 spring 整合配置

1. 保存以下文件,然后在工程启动时加载该文件




	
		
			
				
			
		
		

	

	
		
			
				
			
		
		
			
				
				
			
		
		
			
				
					org.quartz.simpl.RAMJobStore
				
			
		
	
	


整合之后,大家如需要调用定时任务则只需实现Job 接口,然后设置执行时间即可,非常方便。

9 Responses to “Quartz 开源任务调度框架的使用”

  1. Timothy says:

    以前的项目中,用过Quartz.NET,根据java版本的改过来的,呵呵

  2. vaman says:

    我是码盲

  3. zwwooooo says:

    一句都没看懂。板凳休息。

  4. Veezy says:

    恩,技术白,什么也没看懂。。。
    把楼占了好了 😛

Leave a Reply to vaman


正在读取数据……