(一)、調度器是什么?有什么作用?
??調度器(Scheduler)是Quartz框架的心臟,用來管理觸發器和Job,并保證Job能被觸發執行。程序員與框架內部之間的調用都是通過org.quartz.Scheduler接口來完成的。對于Scheduler接口的實現,其實只是核心調度(org.quartz.core.QuartzScheduler)的一個代理,對代理的方法進行調用時會傳遞到底層核心調度實例上。QuartzScheduler處于Quartz框架的根位置,驅動著整個Quartz框架。
(二)、創建調度器
??Scheduler接口有兩個實現類,分別為StdScheduler(標準默認調度器)和RemoteScheduler(遠程調度器),接下來重點講述StdScheduler實例。
??那么如何創建調度器實例呢?大家可能立馬會想到通過new的方式顯式的創建StdScheduler實例。StdScheduler只提供了一個帶參構造方法,此構造需要傳遞QuartzScheduler和SchedulingContext兩個實例參數:
public StdScheduler(QuartzScheduler sched, SchedulingContext schedCtxt)
??然而我們一般不使用構造方法去創建調度器,而是通過調度器工廠來創建。調度器工廠接口org.quartz.SchedulerFactory提供了兩種不同類型的工廠實現,分別是org.quartz.impl.DirectSchedulerFactoryh和org.quartz.impl.StdSchedulerFactory,下面我們分別講述:
(1)、使用DirectSchedulerFactory工廠創建
??此工廠方式創建適用于想絕對控制Scheduler實例的場景,下面用最簡單的方式通過DirectSchedulerFactory創建一個實例:
public static void main(String[] args) {
try {
DirectSchedulerFactory schedulerFactory = DirectSchedulerFactory.getInstance();
// 表示以3個工作線程初始化工廠
schedulerFactory.createVolatileScheduler(3);
Scheduler scheduler = schedulerFactory.getScheduler();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
創建步驟:
??1、通過DirectSchedulerFactory的getInstance方法得到拿到實例
??2、調用createXXX方法初始化工廠
??3、調用工廠實例的getScheduler方法拿到調度器實例
??可以看出,DirectSchedulerFactory是通過createXXX方法傳遞配置參數來初始化工廠,這種初始化方式是一種硬編碼,在工作中用到的情況會很少。
(2)、使用StdSchedulerFactory工廠創建
此工廠是依賴一系列的屬性來決定如何創建調度器實例的。
屬性提供的方式有三種:
??1、通過java.util.Properties屬性實例
??2、通過外部屬性文件提供
??3、通過有屬性文件內容的 java.io.InputStream 文件流提供
public static void main(String[] args) {
try {
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
// 第一種方式 通過Properties屬性實例創建
Properties props = new Properties();
props.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS, "org.quartz.simpl.SimpleThreadPool");
props.put("org.quartz.threadPool.threadCount", 5);
schedulerFactory.initialize(props);
// 第二種方式 通過傳入文件名
// schedulerFactory.initialize("my.properties");
// 第三種方式 通過傳入包含屬性內容的文件輸入流
// InputStream is = new FileInputStream(new File("my.properties"));
// schedulerFactory.initialize(is);
// 獲取調度器實例
Scheduler scheduler = schedulerFactory.getScheduler();
} catch (Exception e) {
e.printStackTrace();
}
}
- 第一種方式向工廠傳入了兩個屬性,分別是線程池的類名和線程池大小,這兩個屬性是必須的,因為工廠沒有給它們指定默認值。
- 第二種方式是通過定義一個外部屬性文件,底層實現是:首先通過Thread.currentThread().getContextClassLoader().getResourceAsStream(filename)獲取文件流,然后使用Properties實例的load方法加載文件流形成屬性實例,最后在通過initialize(props)初始化完成。
- 第三種方式就是直接使用Properties實例的load方法加載文件流形成屬性實例,再在通過initialize(props)初始化完成。
??StdSchedulerFactory工廠還提供了無參數的initialize()方法,此方法本質也是通過加載屬性文件,initialize()方法總是能加載成功的,因為quartz的jar包中有默認的quartz.properties文件,具體的加載步驟:
??1、檢查系統屬性中是否設置了文件名,通過System.getProperty("org.quartz.properties")
??2、如果沒有設置,使用默認的quartz.properties作為要加載的文件名
??3、然后先從當前工作目錄中加載這個文件,如果沒有找到,再從系統 classpath 下加載這個文件
??StdSchedulerFactory工廠還可以不主動調用initialize()方法進行初始化,而是直接使用StdSchedulerFactory的靜態方法getDefaultScheduler()拿到調度器。
(三)、管理調度器
??通過上述方法拿到調度器實例以后,在調度的生命周期中可以做以下工作,例如:啟動調度器,設置調度器為standby模式,繼續或停止調度器。
(1)啟動Scheduler
??當調度器初始化完成,并且Job和Trigger也注冊完成,此時就可以調用scheduler.start()啟動調度器了。start()方法一旦被調用,調度器就開始搜索需要執行的Job。
(2)設置standby模式
??設置Scheduler為standby模式會讓調度器暫停尋找Job去執行。
??應用場景舉例:當需要重啟數據庫時可以先將調度器設置為standby模式,待數據庫啟動完成后再通過start()啟動調度器。
(3)停止調度器
??調用shutdown()或shutdown(boolean waitForJobsToComplete)方法停止調度器。第二個方法表示等待所有正在執行的job執行完畢后才停止調度器。shutdown方法調用后,就不可以再調用start方法了,因為shutdown方法會銷毀Scheduler創建的所有資源(線程、數據庫連接等)。
一般情況下,調度器啟動后不需要做其他任何事情。