Java定時任務Quartz一
阿新 • • 發佈:2019-02-03
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);
}
}