精通Quartz-入門-Job

JobDetail實例,而且,它經過job的類代碼引用這個job來執行。每次調度器執行job時,它會在調用job的execute(..)方法以前建立一個他的實例。這就帶來了兩個事實:1、job必須有一個不帶參數的構造器,2、在job類裏定義數據成員並無意義,由於在每次job執行的時候他們的值會被覆蓋掉。安全

你可能如今想要問「我怎樣給一個job實例提供屬性/配置?」和「在幾回執行間我怎樣能跟蹤job的狀態?」這些問題的答案是同樣的:用JobDataMap- JobDetail對象的一部分。併發

JobDataMap

JobDataMap可以支持任何序列化的對象,當job執行時,這些對象可以在job實例中可用。JobDataMap實現了Java Map接口,它有一些附加的方法,這些方法用來儲存和跟蹤簡單類型的數據。對象

以下代碼能夠很快地給job增長JobDataMap:接口

jobDetail.getJobDataMap().put("jobSays", "Hello World!");進程

jobDetail.getJobDataMap().put("myFloatValue", 3.141f);ip

jobDetail.getJobDataMap().put("myStateData", new ArrayList());文檔

在job執行時,咱們能夠在job裏經過以下代碼獲得JobDataMap:get

public class DumbJob implements Job {io

public DumbJob() {class

}

public void execute(JobExecutionContext context)

throws JobExecutionException

{

String instName = context.getJobDetail().getName();

String instGroup = context.getJobDetail().getGroup();

JobDataMap dataMap = context.getJobDetail().getJobDataMap();

String jobSays = dataMap.getString("jobSays");

float myFloatValue = dataMap.getFloat("myFloatValue");

ArrayList state = (ArrayList)dataMap.get("myStateData");

state.add(new Date());

System.err.println("Instance " + instName + " of DumbJob says: " + jobSays);

}

}

若是用一個持久JobStore(在指南JobStore章節討論),咱們就應該注意在JobDataMap裏放些什麼,由於在它裏面的對象將會被序列化,而且這些對象會所以產生一些class-versioning問題。明顯的,標準Java類型應該是很安全的,可是,任什麼時候候某人改變了一個你已經序列化的實例的類的定義時,咱們就要注意不可以破壞兼容性了。在這個方面的進一步信息能夠在Java Developer Connection Tech Tip: Serialization In The Real World裏找到。咱們能把JDBC-JobStore和JobDataMap放到一個模式裏,在那裏,只有簡單類型和String型能被儲存在Map裏,從而消去任何之後的序列化問題。

Stateful vs. Non-Stateful Jobs

觸發器也有與它們關聯的JobDataMaps。假設咱們有一個儲存在調度器裏被多個觸發器關聯的job,然而,對於每一個獨立的觸發器,我想提供給job不一樣的數據輸入,在這個時候,JobDataMaps就頗有用了。

在job執行期間,JobDataMaps可以在JobExecutionContext裏得到。JobDataMap融合在Trigger和JobDetail類裏,JobDataMap裏面的值可以利用key來更新。

如下例子顯示,在job執行期間從JobExecutionContext裏的JobDataMap獲得數據:

public class DumbJob implements Job {

public DumbJob() {

}

public void execute(JobExecutionContext context)

throws JobExecutionException

{

String instName = context.getJobDetail().getName();

String instGroup = context.getJobDetail().getGroup();

JobDataMap dataMap = context.getJobDataMap(); // 注意:不一樣於之前的例子

String jobSays = dataMap.getString("jobSays");

float myFloatValue = dataMap.getFloat("myFloatValue");

ArrayList state = (ArrayList)dataMap.get("myStateData");

state.add(new Date());

System.err.println("Instance " + instName + " of DumbJob says: " + jobSays);

}

}

StatefulJob

如今,關於job狀態數據的一些附加要點:一個job實例能定義爲"有狀態的"或者"無狀態的"。無狀態的jobs僅當它們在被加入到調度器裏時才存儲JobDataMap。這就意味着,在jobs執行期間對JobDataMap裏數據的任何改變都會丟失,下次執行時job將看不到這些數據。你可能會猜到,一個有狀態的job就是它的反面例子-它的JobDataMap是在每次執行完job後再次儲存的。一個缺點就是有狀態的job不可以併發執行。換句話說,若是job是有狀態的,一個觸發器嘗試觸發這個已經執行了的job時,這個觸發器就會等待直到此次執行結束。

用實現

StatefulJob
接口來標記一個job是有狀態的。

Job 'Instances'

咱們可以建立一個單獨的job類,而且經過建立多個JobDetails實例在調度器裏儲存不少它的「實例定義」,每一個都有它本身的屬性集和JobDataMap ,把它們都加入到調度器裏。

當一個觸發器觸發時,與它關聯的job就是經過配置在調度器上的JobFactory 來實例化的。默認的JobFactory 簡單的調用在job類上的newInstance()方法,你可能想要建立本身的JobFactory實現來完成一些本身想要的事情,如:擁有應用程序的IoC或者DI容器進程/初始化job實例。

job的其餘屬性

這兒有一個其餘屬性的總結,這些屬性是經過JobDetail對象爲一個job實例定義的。

  • 持久性– 若是一個job是非持久的,一旦沒有任何可用的觸發器與它關聯時,他就會自動得從調度器裏被刪除。
  • 不穩定性-若是一個job是不穩定的,他就不會在重起Quartz調度器之間持久化。
  • 請求恢復– 若是一個job「請求恢復」,在調度器「硬關閉」(如:該進程崩潰,機器被關掉)時這個job還在執行,事後,當調度器再次啓動時,他就會再次執行。在這種狀況下,JobExecutionContext.isRecovering() 方法將會返回true.
  • Job監聽器 –一個job可以有0個或者多個與它關聯的監聽器。當job執行時,監聽器就會被通知。在監聽器的更多討論請看TriggerListeners & JobListeners

JobExecutionException

最後,咱們來看看Job.execute(..)方法的一些細節。你可以從execute方法裏拋出的僅有的異常類型就是JobExecutionException。由於這樣,咱們應該使用try-catch塊包圍整個execute方法內容。咱們還應該花一些時間看看JobExecutionException文檔。當job執行發生異常時,經過設置JobExecutionException,可讓此job再次進入調度器或者從此再也不運行。

相關文章
相關標籤/搜索