1. 程式人生 > >Java定時任務Quartz一

Java定時任務Quartz一

1.概要

      Quartz是由OpenSymphony提供的強大的開源任務排程框架。官網地址:http://www.quartz-scheduler.org/,純Java實現。

  • 強大的排程功能:很容易與Spring整合,提供排程執行環境的持久化機制,儲存並恢復任務排程現場。即使系統因故障關閉,任務排程現場資料也不會丟失;
  • 靈活的應用方式:允許靈活的定義觸發器的排程時間表,並可以對觸發器和任務進行關聯對映,提供了元件式的監聽器、各種外掛、執行緒池等功能,支援任務和排程的多種組合方式、支援排程資料的多種儲存方式,支援分散式和叢集操作;
  • 主要用到的設計模式:Builder模式、Factory模式、元件模式、鏈式寫法;
  • 核心概念:排程器——負責定期、定時、定頻率的去執行任務;任務——具體的業務邏輯;觸發器——排程器排程任務的時間;
  • 重要組成:Job——介面且可以接收引數;JobDetail——Job的實現類和相關的靜態資訊;JobBuilder——定義或者建立JobDetail的例項;JobStore——用來儲存Job資料;Trigger——描述觸發Job執行時的時間觸發規則;TriggerBuilder——定義或者建立觸發器的例項;ThreadPool——執行緒池Job執行的基礎設施;Scheduler——Quartz獨立執行的容器;Calendar——一個Trigger可以和多個Calendar關聯,以排除或者包含某些時間點;監聽器——JobListener、TriggerListener、SchedulerLIstener監聽對應的元件。

2.Quartz的基本使用

1.每兩秒鐘列印一次Hello World:

建立Job實現類HelloJob

package com.luna.timer.quarts;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class HelloJob implements Job{
	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		//列印當前執行時間
		Date startTime = new Date();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("任務執行時間為:"+sf.format(startTime));
		System.out.println("Hello World");
	}
}

建立Job測試類HelloScheduler

package com.luna.timer.quarts;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class HelloScheduler {
	public static void main(String[] args) throws SchedulerException {
		// 建立一個JobDetail例項與HelloJob類繫結
		JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("myJob", "group1").build();
		// 建立一個Trigger例項,定義該Job立即執行,且每隔兩秒鐘執行一次直到永遠
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity("mtTrigger", "group1").startNow()
				.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();
		//建立scheduler例項
		SchedulerFactory sFactory = new StdSchedulerFactory();
		Scheduler scheduler = sFactory.getScheduler();
		scheduler.start();
		//列印當前時間
		Date startTime = new Date();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("列印當前時間:"+sf.format(startTime));
		scheduler.scheduleJob(jobDetail,trigger);
	}
}
2.淺談Job&JobDetail

     Job:實現業務邏輯的任務介面,job介面非常容易實現,只有一個execute方法,類似TimerTask的run方法,在裡面編寫業務邏輯。Job在Quartz中的生命週期:每次排程器執行Job時,它在呼叫execute方法前會建立一個新Job例項;當呼叫完成後,關聯的job物件例項會被釋放,釋放的例項會被垃圾回收機制回收。JobDetail為job提供了很多設定屬性name、group、jobClass、jobDataMap(用來儲存特定Job例項的狀態資訊),排程器需要藉助JobDetail物件來新增Job例項。

package com.luna.timer.quarts;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class HelloScheduler {
	public static void main(String[] args) throws SchedulerException {
		// 建立一個JobDetail例項與HelloJob類繫結
		JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("myJob", "group1").build();
		System.out.println("JobDetail's name:"+jobDetail.getKey().getName());
		System.out.println("JobDetail's group:"+jobDetail.getKey().getGroup());
		System.out.println("JobDetail's jobClass:"+jobDetail.getJobClass().getName());
		// 建立一個Trigger例項,定義該Job立即執行,且每隔兩秒鐘執行一次直到永遠
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity("mtTrigger", "group1").startNow()
				.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();
		//建立scheduler例項
		SchedulerFactory sFactory = new StdSchedulerFactory();
		Scheduler scheduler = sFactory.getScheduler();
		scheduler.start();
		//列印當前時間
		Date startTime = new Date();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("列印當前時間:"+sf.format(startTime));
		scheduler.scheduleJob(jobDetail,trigger);
	}
}
3.淺談JobExecutionContext&JobDataMap

      當Schedule呼叫一個Job,就會將JobExecutionContext傳遞給Job的execute方法;Job能通過JobExecutionContext物件訪問到Quartz執行時的環境以及Job本身的明細資料。在進行任務排程時,JobDataMap儲存在JobExecutionContext中,非常方便獲取;JobDataMap可以用來裝載任何可序列化的資料物件,當job例項物件被執行時這些引數物件會傳遞給它;JobDataMap實現了JDK的Map介面,並且添加了一些非常方便的方法用來存取基本資料型別。獲取JobDataMap的兩種方式:

  • 從Map中直接獲取,示例程式碼如下Job:
package com.luna.timer.quarts;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
public class HelloJob implements Job{
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		//列印當前執行時間
		Date startTime = new Date();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("任務執行時間為:"+sf.format(startTime));
		JobKey key = context.getJobDetail().getKey();
		System.out.println("My job name and group are:"+key.getName()+":"+key.getGroup());
		TriggerKey triggerKey = context.getTrigger().getKey();
		System.out.println("My trigger name and group are:"+triggerKey.getName()+":"+triggerKey.getGroup());
		JobDataMap jobMap = context.getJobDetail().getJobDataMap();
		JobDataMap triggerMap = context.getTrigger().getJobDataMap();
//		JobDataMap dataMap = context.getMergedJobDataMap(); //獲取合併處理後的引數集合
		String jobMsg = jobMap.getString("message");
		Float floatValue = jobMap.getFloat("float");
		String triggerMsg = triggerMap.getString("triggerMsg");
		Double doubleValue = triggerMap.getDouble("double");
		System.out.println("My job params are:"+jobMsg+":"+floatValue);
		System.out.println("My trigger params are:"+triggerMsg+":"+doubleValue);
	}
}

示例程式碼Schedule:

package com.luna.timer.quarts;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class HelloScheduler {
	public static void main(String[] args) throws SchedulerException {
		// 建立一個JobDetail例項與HelloJob類繫結
		JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("myJob", "group1").
				usingJobData("message", "Hello MyJob1").usingJobData("float", 3.14F).build();
		
		//如果傳遞引數過程中key相同,則trigger的引數值會覆蓋jobdetail裡面的引數值
		// 建立一個Trigger例項,定義該Job立即執行,且每隔兩秒鐘執行一次直到永遠
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity("mtTrigger", "group1").
				usingJobData("triggerMsg", "Hello MyTrigger1").usingJobData("double", 2.0D).
				startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().
						withIntervalInSeconds(2).repeatForever()).build();
		//建立scheduler例項
		SchedulerFactory sFactory = new StdSchedulerFactory();
		Scheduler scheduler = sFactory.getScheduler();
		scheduler.start();
		//列印當前時間
		Date startTime = new Date();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("列印當前時間:"+sf.format(startTime));
		scheduler.scheduleJob(jobDetail,trigger);
	}
}
  • Job實現類中新增setter方法對應JobDataMap的鍵值(Quartz框架預設的JobFactory實現類在初始化Job例項物件時會自動地呼叫這些setter方法),如下程式碼所示Job:
package com.luna.timer.quarts;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
public class HelloJob implements Job{
	private String message;
	private Float floatValue;
	private Double doubleValue;
	
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
	public Float getFloatValue() {
		return floatValue;
	}
	public void setFloatValue(Float floatValue) {
		this.floatValue = floatValue;
	}
	public Double getDoubleValue() {
		return doubleValue;
	}
	public void setDoubleValue(Double doubleValue) {
		this.doubleValue = doubleValue;
	}
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		//列印當前執行時間
		Date startTime = new Date();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("任務執行時間為:"+sf.format(startTime));
		JobKey key = context.getJobDetail().getKey();
		System.out.println("My job name and group are:"+key.getName()+":"+key.getGroup());
		TriggerKey triggerKey = context.getTrigger().getKey();
		System.out.println("My trigger name and group are:"+triggerKey.getName()+":"+triggerKey.getGroup());
		System.out.println("Message is:"+message);
		System.out.println("Float is:"+floatValue);
		System.out.println("Double is:"+doubleValue);
	}
}

示例程式碼Schedule:

package com.luna.timer.quarts;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class HelloScheduler {
	public static void main(String[] args) throws SchedulerException {
		// 建立一個JobDetail例項與HelloJob類繫結
		JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("myJob", "group1").
				usingJobData("message", "Hello MyJob1").usingJobData("floatValue", 3.14F).build();
		
		//如果傳遞引數過程中key相同,則trigger的引數值會覆蓋jobdetail裡面的引數值
		// 建立一個Trigger例項,定義該Job立即執行,且每隔兩秒鐘執行一次直到永遠
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity("mtTrigger", "group1").
				usingJobData("triggerMsg", "Hello MyTrigger1").usingJobData("doubleValue", 2.0D).
				startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().
						withIntervalInSeconds(2).repeatForever()).build();
		//建立scheduler例項
		SchedulerFactory sFactory = new StdSchedulerFactory();
		Scheduler scheduler = sFactory.getScheduler();
		scheduler.start();
		//列印當前時間
		Date startTime = new Date();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("列印當前時間:"+sf.format(startTime));
		scheduler.scheduleJob(jobDetail,trigger);
	}
}