Quartz任务调度框架的学习1

      系统开发中,经常需要用到周期性执行某个任务的需求,或者资源上的调度,给谁分配,谁等待问题,之前,一直是个菜鸟,只知道用sun提供了java.util.Timer和TimerTask的简单调度功能,今天知道了Quartz开源任务调度框架,并学习到了Spring关于任务调度的集成。一起来学习下吧。

      Quartz是任务调度的开源框架,使用它,我们可以很容易的开发出系统中需要的任务调度模块,包括资源的调度,Quartz前后出现了许多版本,本文就 主要根据quartz最新版本2.2.1进行讲述,不同版本可能里面类的创建和实例化有所差异,使用时最好去看一下doc文档。

     Quartz中有三个核心概念,调度器,任务,和触发器。有以下的核心类和接口。

Job

接口,void  execute(JobExecutionContext context)实现该接口定义需要执行的任务。jobExectutionContext类提供了调度上下文的各种信息,job运行时信息保存于JobDataMap实例中。

StatefulJob接口是Job子接口,表示有状态的任务。

JobDetail

JobDetail类承担了描述Job实现类和其他相关静态信息(Job名称、描述、关联监听器)。

JobDetail(String name ,String group,Class jobClass)要求指定Job实现类,任务在Scheduler中的组名和Job名称

Trigger 描述Job执行的时间触发规则。主要有SimpleTrigger和CronTrigger两个子类。SimpleTrigger负责仅触发一次或固定时间间隔周期性执行。CronTrigger可以通过Cron表达式定义出复杂的调度方案
Calendar ogr.quartz.Calendar是一些日历特定时间点的集合,可以看做java,util.Calendar集合,一个Trigger可以与多个Calendar相关联 ,用于排除你或包含某些时间点。若干子类,AnnualCalendar、MonthlyCalendar、WeeklyCalendar
Scheduler

表示一个Quartz独立运行容器,Trigger和jobDetail可以注册到Scheduler中,在Scheduler中拥有各自的组和名称。组和名称是Scheduler查找定位容器内某一对象的依据。它将Trigger绑定到JobDetail中,Trigger触发,job就被执行。

Scheduler可以通过SchedulerFactory创建,通过Scheduler#getContext()获取SchedulerContext上下文信息,job和Trigger就可以访问这些信息了。

ThreadPool Scheduler使用线程池作为任务运行的基础,任务通过共享线程池中的线程提高运行效率

   

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class SimpleJob implements Job {
	



//①实例Job接口方法

public void execute(JobExecutionContext jobCtx)throws JobExecutionException {
   
  System.out.println(jobCtx.getTrigger().getDescription()+ " triggered. time is:" + (new Date()));

}

}

    

import java.util.Date;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.SimpleTriggerImpl;

public class SimpleTriggerRunner {
	
	public static void main(String[] args) {
		
		try{
		//①创建一个JobDetail实例,指定SimpleJob

		JobDetail jobDetail = new JobDetailImpl("job1_1","jGroup1", SimpleJob.class);

		//②通过SimpleTrigger定义调度规则:马上启动,每2秒运行一次,共运行100次

	
		SimpleTriggerImpl simpleTrigger = new SimpleTriggerImpl("trigger1_1","tgroup1");

		simpleTrigger.setStartTime(new Date());

		
		simpleTrigger.setDescription("SimpleTriggerRunner");

		simpleTrigger.setRepeatInterval(2000);

		simpleTrigger.setRepeatCount(100);

		//③通过SchedulerFactory获取一个调度器实例

		SchedulerFactory schedulerFactory = new StdSchedulerFactory();

		Scheduler scheduler = schedulerFactory.getScheduler();

		scheduler.scheduleJob(jobDetail, simpleTrigger);
		
		//④ 注册并进行调度

		scheduler.start();//⑤调度启动

		}catch (Exception e) {

		e.printStackTrace();

		}
    }

}

    

    

import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.CronTriggerImpl;

public class CronTriggerRunner {
	
	public static void main(String[] args) {
		try {
			JobDetailImpl jobDetail=new JobDetailImpl();
			jobDetail.setName("job1_2");
			jobDetail.setGroup("jGroup1");
			jobDetail.setJobClass(SimpleJob.class);
			
			CronTriggerImpl cronTrigger=new CronTriggerImpl();
			cronTrigger.setName("trigger1_2");
			cronTrigger.setGroup("tgroup1");
			cronTrigger.setDescription("cronTrgger");
			cronTrigger.setCronExpression("0/5 1 * * * ?");
			
			SchedulerFactory schedulerFactory = new StdSchedulerFactory();

			Scheduler scheduler = schedulerFactory.getScheduler();

			scheduler.scheduleJob(jobDetail, cronTrigger);
			

			scheduler.start();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

}

   

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.quartz.DateBuilder;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.AnnualCalendar;
import org.quartz.impl.triggers.SimpleTriggerImpl;

public class CalendarExample {
	
	public static void main(String[] args) {
		try{
			SchedulerFactory sf=new StdSchedulerFactory();
			Scheduler scheduler=sf.getScheduler();
			AnnualCalendar holidays=new AnnualCalendar();
			
			Calendar laborDay=new GregorianCalendar();
			laborDay.add(Calendar.MONTH, 5);
			laborDay.add(Calendar.DATE, 28);
			
			Calendar nationtialDay=new GregorianCalendar();
			nationtialDay.add(Calendar.MONTH, 10);
			nationtialDay.add(Calendar.DATE, 1);
			
			ArrayList<Calendar> calendars=new ArrayList<Calendar>();
			calendars.add(laborDay);
			calendars.add(nationtialDay);
			
			holidays.setDaysExcluded(calendars);
			
			scheduler.addCalendar("holidays", holidays, false, false);
			
			
		   Date  runDate=DateBuilder.dateOf(10, 0, 0, 1, 4);
		  
			
			JobDetailImpl jobDetail=new JobDetailImpl();
			jobDetail.setName("job1");
			jobDetail.setGroup("group1");
			jobDetail.setJobClass(SimpleJob.class);
			jobDetail.setDescription("Calendar job");
			
			SimpleTriggerImpl simpleTrigger=new SimpleTriggerImpl();
			simpleTrigger.setName("trigger1");
			simpleTrigger.setGroup("group1");
			simpleTrigger.setStartTime(runDate);
			simpleTrigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
			simpleTrigger.setRepeatInterval(60L*1000L);
			simpleTrigger.setCalendarName("holidays");
			
			scheduler.scheduleJob(jobDetail, simpleTrigger);
			scheduler.start();
			
			
			
			
			
		}catch(Exception e){
			
		}
		
		
	}

}

    注:如果以上看到的与你在其他例子上看到的有所差异是应为这是基于quartz最新包quartz-2.2.1-distribution.zip写的,编译通过的。

    CronTrigger CronExpression详解:

    Quartz利用linux下cron表达式定义时间规则,由6或7个空格分隔的时间字段组成

位置 时间域名 允许值 允许的特殊字符
 1  秒  0-59  ,- * /
 2  分钟  0-59   ,- * /
 3  小时  0-23   ,- * /
 4 日期   1-31   ,- *  ? /  L W C
 5 月份   1-12   ,- * /
 6  星期  1-7   ,- * ?  /  L  C #
 7 年(可选)   空值 1970-2099   ,- * /

特殊字符介绍:

*  可用于所有字段,表示对应时间域的每一时刻

? 在日期和星期字段中使用,表示无意义的值,相当于占位符

-   表达一个范围,如小时字段 10- 12 表示10点到12点

,表示 一个列表值,如星期字段使用 MON,FRI,WED 表示星期一,星期五和星期三

/    x/y表示一个等步长序列,x表示起始值,y为增量步长值,分钟字段使用0/15 表示 0,15,30,45秒。*/y等同于0/y

L  Last 在日期和星期字段中使用,6L在星期字段中表示这个月的最后星期五

W ,只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。15W 。离这个月15号最近的工作日,不能够夸月

LW 当月的最后一个工作日

#  只用在星期字段,表示当月的某个工作日。 6#3 当月的第三个星期五, 5#4当月的第4个星期四,如果没有第四个星期四则默认不触发

C  该字符只能用在日期和星期字段,代表Calendar。例如:5C在日期字段中相当于5日以后的第一天,在星期字段中相当于星期四后的第一天。

     

  

任务调度信息存储:

       quartz将所有的任务调度的执行信息保存在内存中,这样做缺乏数据的持久性,Quartz允许用户调整其属性文件将任务调度的执行信息持久化到数据库中。

      Quartz  JAR包 ogr.quartz包下有个quartz.properties属性配置文件,其包含了1)集存信息,2)调度器线程池 3)任务调度现场数据的存储。

    quartz.proeprteis默认配置

# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#

org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000

org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

    

    可以通过修改配置将任务调度现场保存至数据库中

    org.quartz.jobStore.class: org.quartz.impl.jdbcJobStore.JobStoreTX

    org.quartz.jobStore.tablePrefix=QRTZ_

    org.quartz.jobStore.dataSource=qzDS

    org.quartz.dataSource.qzDS.Driver=

    org.quartz.dataSource.qzDS.URL=

    org.quartz.dataSource.qzDS.user=

    org.quartz.dataSource.qzDS.password=

    org.quartz.dataSource.qzDS.maxConnections=

    需要创建数据库,在doc/dbTables下有不同的数据库脚本,执行一遍即可。

   

    

  

   

猜你喜欢

转载自pupin9.iteye.com/blog/2056151