Quartz簡介
看到一個不錯的使用quartz的總結博客,Mark一下。傳送門:https://www.cnblogs.com/drift-ice/p/3817269.html
特點:
- 強大的調度功能
- 靈活的應用方式
- 分佈式和集羣能力
用的的設計模式
- Builder模式
- Factory模式
- 組件模式
- 鏈式寫法
Quartz體系結構
核心概念
- 調度器(scheduler):將JobDetail和trigger綁定在一起。包括如下方法:
- start
- stop
- pause
- resume
- …
- 任務(JobDetail):包含任務的實現類和類的一些信息
- 觸發器(trigger):決定任務什麼時候被調用,有如下兩種:
- SimpleTrigger(類似timer)
- CronTrigger(更復雜)
重要組成
- Job:接口
- JobDetail:
- JobBuilder:創建JobDetail的實例
- JobStore:接口
- Trigger:
- TriggerBuilder:創建Trigger的實例
- ThreadPool:
- Scheduler
- Calendar:一個Trigger可以和多個Calendar關聯,以排除或包含某些時間點。
- 監聽器:包括JobListener、TriggerListener、SchedulerListener。
Job&JobDetail
Job
Job接口非常容易實現,只有一個execute方法,類似TimerTask的run方法,在裏面編寫業務邏輯。
源碼如下:
package org.quartz;
public abstract interface Job {
public abstract void execute(JobExecutionContext paramJobExecutionContext)
throws JobExecutionException;
}
Job實例在Quartz中的生命週期:
每次調度器執行job時,它在調用execute方法前會創建一個新的job實例。
當調用完成後,關聯的job對象實例會被釋放,釋放的實例會被垃圾回收機制回收。
JobDetail
JobDetail爲Job實例提供了很多設置屬性,以及JobDataMap成員變量屬性,它用來存儲特定Job實例的狀態信息,調度器需要藉助JobDetail對象來添加Job實例。
重要屬性:
- name
- gruop:默認DEFAULT
- jobClass
- jobDataMap
JobExecutionContext
- 當Scheduler調用一個Job,就會將JobExecutionContext傳遞給Job的execute()方法;
- Job能通過JobExecutionContext對象訪問到Quartz運行時候的環境以及Job本身的明細數據。
JobDataMap
JobDataMap是什麼
- 在進行任務調度時JobDataMap存儲在JobExecutionContext中,非常方便獲取。
- JobDataMap可以用來裝載任何可序列化的數據對象,當Job實例對象被執行時這些參數對象會傳遞給它。
- JobDataMap實現了JDK的Map接口,並且添加了一些非常方便的方法用來存取基本數據類型。
獲取JobDataMap的兩種方式
- 從Map中直接獲取
- Job實現類中添加setter方法對應JobDataMap的鍵值(Quartz框架默認的JobFactory實現類在初始化job實例對象時會自動地調用這些setter方法)
淺談Trigger
Quartz中的觸發器是用來告訴調度程序作業什麼時候觸發。即Trigger對象是用來觸發執行Job的。
觸發器通用屬性
JobKey
表示job實例的標識,觸發器被觸發時,該指定的job實例會執行。
StartTime
表示觸發器的時間表首次被觸發的時間。它的值的類型是java.util.Date。
EndTime
指定觸發器的不再被觸發的時間。它的值是java.util.Date。
SimpleTrigger
在一個指定時間段內執行一次作業任務或是在指定的時間間隔內多次執行作業任務
需要注意的點:
- 重複次數可以爲0,正整數或是SimpleTrigger.REPEAT_INDEFINITELY常量
- 重複執行間隔必須爲0或長整數
- 一旦被指定了endTime參數,那麼它會==覆蓋重複次數參數==的效果
CronTrigger
基於日曆的作業調度器,而不是像SimpleTrigger那樣精確指定間隔時間,比SimpleTrigger更常用。
- Cron表達式(類似Linux中的CronTable)
用於配置CronTrigger實例。
是由7個表達式組成的字符串,描述了時間表的詳細信息。
格式:[秒] [分] [小時] [日] [月] [周] [年](中間有空格)
詳解如下:http://www.cnblogs.com/yaowen/p/3779284.html
Cron表達式小提示
- ’L’和’W’可以組合使用
- 周字段英文字母不區分大小寫即MON和mon相同
- 利用工具,在線生成。傳送門:http://cron.qqe2.com
淺談Scheduler
Scheduler-所有的Scheduler實例應該由SchedulerFactory來創建。
Scheduler的創建方式:
/*
* 創建Scheduler的方式一
*/
//創建Scheduler實例
SchedulerFactory sfact = new StdSchedulerFactory();
Scheduler scheduler = sfact.getScheduler();
scheduler.start();
//將JobDetail和Trigger綁定到schedule上,執行調度器
scheduler.scheduleJob(jobDetail, trigger);
/*
* 創建Scheduler的方式二
*/
//創建Scheduler實例
DirectSchedulerFactory factory = DirectSchedulerFactory.getInstance();
Scheduler scheduler2 = factory.getScheduler();
scheduler.start();
//將JobDetail和Trigger綁定到schedule上,執行調度器
scheduler.scheduleJob(jobDetail, trigger);
STDSchedulerFactory
- 使用一組參數(Java.util.Properties)來創建和初始化Quartz調度器
- 配置參數一般存儲在quartz.properties中
- 調用getScheduler方法就能創建和初始化調度器對象
Scheduler的主要參數
- Date scheduleJob(JobDetail jobDetail, Trigger trigger):將JobDetail和Trigger綁定,註冊到Scheduler調度器中,執行調度任務。
- void start():啓動Scheduler
- void standby():暫時掛起Scheduler,再次執行start可以繼續執行
void shutdown():關閉scheduler
可以傳入一個boolean參數:
- shutdown(true): 表示等待所有正在執行的job執行完畢之後,再關閉scheduler
- shutdown(false):直接關閉scheduler,默認。
demo演示如下
- 自定義Job任務 HelloJob
package lxd.quartz.demo;
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.Trigger;
import org.quartz.TriggerKey;
/**
*
* Quartz hello demo
*
* <pre>
* Quartz hello demo
* </pre>
*
* @author lixiaodong
* @date 2017年7月2日
* @since 1.0
*
*/
public class HelloJob implements Job {
private String message;
private Float FloatJobValue;
private Double DoubleTriggerValue;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Float getFloatJobValue() {
return FloatJobValue;
}
public void setFloatJobValue(Float floatJobValue) {
FloatJobValue = floatJobValue;
}
public Double getDoubleTriggerValue() {
return DoubleTriggerValue;
}
public void setDoubleTriggerValue(Double doubleTriggerValue) {
DoubleTriggerValue = doubleTriggerValue;
}
public void execute(JobExecutionContext context) throws JobExecutionException {
/*try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
// 打印當前的執行時間,格式爲2017-01-01 00:00:00
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("\nCurrent Exec Time is : " + sf.format(date));
// System.out.println("Hello World");
/*JobKey key = context.getJobDetail().getKey();
TriggerKey trKey = context.getTrigger().getKey();*/
// JobDataMap dataMap = context.getJobDetail().getJobDataMap();
// JobDataMap tdataMap = context.getTrigger().getJobDataMap();
// JobDataMap dataMap = context.getMergedJobDataMap();
/*System.out.println("my job name and group are: " + key.getName()
+ ":" + key.getGroup());
System.out.println("my trigger name and group are: " + trKey.getName()
+ ":" + trKey.getGroup());*/
// String jobMsg = dataMap.getString("message");
// Float jobFloatValue = dataMap.getFloat("FloatJobValue");
// System.out.println("JobMsg is: " + jobMsg);
// System.out.println("JobFloatValue is: " + jobFloatValue);
// String triggerMsg = tdataMap.getString("message");
// Double triggerDoubleValue = tdataMap.getDouble("DoubleTriggerValue");
// String triggerMsg = dataMap.getString("message");
// Double triggerDoubleValue = dataMap.getDouble("DoubleTriggerValue");
// System.out.println("TriggerMsg is: " + triggerMsg);
// System.out.println("DoubleTriggerValue is: " + triggerDoubleValue);
/*System.out.println("JobMsg is: " + message);
System.out.println("JobFloatValue is: " + FloatJobValue);
System.out.println("TriggerMsg is: " + message);
System.out.println("DoubleTriggerValue is: " + DoubleTriggerValue);*/
/*
* 獲取trigger的信息
*/
/*Trigger currentTrigger = context.getTrigger();
System.out.println("start Time is: " + sf.format(currentTrigger.getStartTime()));
System.out.println("end Time is: " + sf.format(currentTrigger.getEndTime()));
JobKey jobKey = currentTrigger.getJobKey();
System.out.println("JobKey info---"
+ "jobName: " + jobKey.getName()
+ " jobGroup: " + jobKey.getGroup());*/
/*
* simpleTrigger
*/
System.out.println("hello world");
}
}
- 自定義Scheduler調度器HelloSchedule
package lxd.quartz.demo;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.impl.DirectSchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
/**
*
* 執行Job的調度器Schedule
*
* <pre>
* 執行Job的調度器Schedule
* </pre>
*
* @author lixiaodong
* @date 2017年7月2日
* @since 1.0
*
*/
public class HelloSchedule {
public static void main(String[] args) throws SchedulerException, InterruptedException {
/*
* 測試trigger的startTime和endTime
*/
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("\nHelloSchedule Current Time is : " + sf.format(date));
//創建JobDetail實例,將該實例和Job綁定
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("myJob", "group1")
/*
* 使用JobDataMap
*/
/*.usingJobData("message", "hello myJob1")
.usingJobData("FloatJobValue", 3.14F)*/
.build();
//獲取距離當前時間3秒後的時間
// date.setTime(date.getTime() + 3000);
// //獲取距離當前時間6秒後的時間
// Date endDate = new Date();
// endDate.setTime(endDate.getTime() + 6000);
/*
* jobDetail的屬性
*/
/*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("myTrigger", "group1")
/*
* 使用JobDataMap
*/
/*.usingJobData("message", "hello myTrigger1")
.usingJobData("DoubleTriggerValue", 2.0D)*/
// .startNow()
/*
* 測試trigger的startTime和endTime
*/
// .startAt(date)
// .endAt(endDate)
// .withSchedule(
// SimpleScheduleBuilder
// .simpleSchedule()
// .withIntervalInSeconds(2)
// .repeatForever()
// )
// .build();
/*
* SimpleTrigger
*/
date.setTime(date.getTime() + 4000L);
//獲取距離當前時間6秒後的時間
Date endDate = new Date();
endDate.setTime(endDate.getTime() + 6000);
/*SimpleTrigger trigger = (SimpleTrigger)TriggerBuilder
.newTrigger()
.withIdentity("myTrigger", "group1")
//距離當前時間4秒後執行
.startAt(date)
.endAt(endDate)
//距離當前時間4秒後首次執行任務,之後每隔2秒重複執行一次任務
.withSchedule(SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(2)
//循環執行次數無窮
// .withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY))
//重複3次
.withRepeatCount(3))
.build();*/
/*
* CronTrigger cron表達式
*/
CronTrigger trigger = (CronTrigger)TriggerBuilder
.newTrigger()
.withIdentity("myTrigger", "group1")
.withSchedule(
//每秒鐘執行一次任務
CronScheduleBuilder.cronSchedule("* * * * * ? *"))
.build();
/*
* 創建Scheduler的方式一
*/
//創建Scheduler實例
SchedulerFactory sfact = new StdSchedulerFactory();
Scheduler scheduler = sfact.getScheduler();
scheduler.start();
//將JobDetail和Trigger綁定到schedule上,執行調度器
System.out.println("scheduled time is: " + scheduler.scheduleJob(jobDetail, trigger));
//執行兩秒後,掛起scheduler
Thread.sleep(2000L);
scheduler.standby();
//執行兩秒後,關閉scheduler,不能重新啓動
// Thread.sleep(2000L);
// scheduler.shutdown();
//掛起3秒後繼續執行
Thread.sleep(3000L);
scheduler.start();
/*
* 創建Scheduler的方式二
*/
//創建Scheduler實例
// DirectSchedulerFactory factory = DirectSchedulerFactory.getInstance();
// Scheduler scheduler2 = factory.getScheduler();
// scheduler.start();
// //將JobDetail和Trigger綁定到schedule上,執行調度器
// scheduler.scheduleJob(jobDetail, trigger);
}
}