最近須要寫一個天天定點自動執行的定時任務,對於之前本身寫小項目,可能會選擇java自帶的Timer類,可是對於公司中的項目,Timer類實現定時任務只能有一個後臺線程執行任務,而且只能讓程序按照某個頻度執行,並不能在指定時間點執行。同時因爲通常大型項目會有多個job分別須要在不一樣的時間點自動執行,單線程的Timer知足不了需求。而任務調度框架Quartz恰好知足這些需求,我是實習公司的項目中就已經配置好了這個框架,在使用的時候瞭解了這個quartz,現總結以下。html
Quartz是OpenSymphony開源組織在Job scheduling領域又一個開源項目,徹底由Java開發,能夠用來執行定時任務,相似於java.util.Timer。可是相較於Timer, Quartz增長了不少功能:
持久性做業 - 就是保持調度定時的狀態;
做業管理 - 對調度做業進行有效的管理;
複製代碼
quartz主要包括三個部分的模塊,定時任務Job、觸發器Trigger、調度器Scheduler。
簡單的流程就是:調度器根據觸發器來執行任務。java
//預約義Job接口--pom.xml須要加載依賴的包
public interface Job {
void execute(JobExecutionContext var1) throws JobExecutionException;
}
//任務邏輯經過實現Job接口,而且重寫execute方法,將須要執行的邏輯實現寫在execute函數中
public class TestJob implements Job {
/**把要執行的操做,寫在execute方法中 */
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println("I can do something...");
System.out.println(sdf.format(new Date()));
}
}
參考:https://juejin.im/post/5a0c08c5f265da4335624c8f
//1. 建立一個JodDetail實例 將該實例與Hello job class綁定 (鏈式寫法)
JobDetail jobDetail = JobBuilder.newJob(QuartzOrderReturn.class)// 定義Job類爲QuartzOrderReturn類,這是真正的執行邏輯所在
.withIdentity(StrUtils.uuid())
.setJobData(jobDataMap)
.build();
複製代碼
//建立SimpleTrigger startTime end 分別表示觸發器的首次觸發時間和再也不被觸發的時間
SimpleTrigger trigger = newTrigger()
.withIdentity("trigger", "group")
.startAt(startTime)
.endAt(end)
.withSchedule(
simpleSchedule().withIntervalInHours(
executeFrequency).withRepeatCount(
executeBatch)).build();
複製代碼
CronTrigger 能夠配置更復雜的觸發時刻表,基於日曆的做業觸發器。使用SimpleTrigger觸發器須要設置不一樣的屬性支撐,代碼編寫比較多,而且不靈活。而CornTrigger就比較靈活,能夠經過設計Corn表達式來控制複雜的觸發時間表。算法
Corn表達式:用於配置CornTrigger實例,由7個表達式組成的字符串,描述了時間表的詳細信息。bash
//建立CornTrigger 好比下面的就是設計天天中午十二點整觸發
CronTrigger trigger = newTrigger().withIdentity(triggerKey).withSchedule(cronSchedule("0 0 12 * * ?")).build();
// 把job和trigger加入調度
scheduler.scheduleJob(jobDetail, trigger);
//啓動scheduler
scheduler.start();
複製代碼
// 把job和trigger加入調度
scheduler.scheduleJob(jobDetail, trigger);
//啓動scheduler
scheduler.start();
複製代碼
//一個完整的實例
private void quartzOrderReturn(List<String> returnIds) {
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("returnIds", returnIds);
//1. 建立一個JodDetail實例 將該實例與Hello job class綁定 (鏈式寫法)
JobDetail jobDetail = JobBuilder.newJob(QuartzOrderReturn.class)// 定義Job類爲QuartzOrderReturn類,這是真正的執行邏輯所在
.withIdentity(StrUtils.uuid())
.setJobData(jobDataMap)
.build();
// 2. 定義一個Trigger,定義該job在10秒後執行,而且執行一次
Date startTime = new Date();
startTime.setTime(startTime.getTime() + 10000L);
SimpleTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(StrUtils.uuid(), HeaderNameConstants.getQuartzTrigger()).startNow()// 定義名字和組
.startAt(startTime)
.withSchedule(SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(2)//定義時間間隔是2秒
.withRepeatCount(0)//定義重複執行次數是無限次
)
.build();
// 4. 將trigger和jobdetail加入這個調度
scheduler.scheduleJob(jobDetail, trigger);
// 5. 啓動scheduler
scheduler.start();
// 6. 任務執行後20秒後休眠
Thread.sleep(startTime.getTime() + 20000L);
// 7. 若是定時任務開啓則關閉
if (scheduler.isStarted()) {
scheduler.shutdown(true);
}
} catch (SchedulerException | InterruptedException e) {
e.printStackTrace();
}
}
複製代碼
//每一個2秒執行一次
string cronParam = "*/2 * * * * ?";
//建立計劃任務抽象工廠
ISchedulerFactory sf = new StdSchedulerFactory();
//建立計劃任務
IScheduler sched = sf.GetScheduler();
//建立job
JobDetail job = new JobDetail("myJob","group", typeof(MyJob));
//建立觸發器
Trigger trigger = new CronTrigger("myTrigger","group",cronParam);
//將job和trigger注入到計劃任務中
sched.ScheduleJob(job, trigger);
//啓動計劃任務
sched.Start();
//關閉計劃任務
//sched.Shutdown();
複製代碼
定時通常是使用時間輪(time wheel)算法實現。 時間輪算法簡單來講能夠用下圖表示,其主體是一個循環列表,框架
參考連接:www.zhihu.com/question/41… www.kafka.cc/archives/24…ide
1.抽象封裝Job類函數
2.頁面管理多個定時任務post