六合彩最高极限

【Quartz指南】更多關于Jobs & JobDetails

Jobs很容易實現,這兒有更多我們需要理解的東西:jobs的本質,job接口的execute(..)方法,關于JobDetails

當我們實現的一個class是真正的”job”時,Quartz需要知道各種job有的屬性,這是通過JobDetail類做到的。在沒用JobDetail之前,JobDetail的功能的實現是通過在每個job的實現類上加上所有的現在JobDetail的get方法來實現的。這就在每個job類上強加了一些實現一樣功能的代碼,就顯得每個job類很笨重,于是,Quartz開發者們就創造了JobDetail類。

現在,我們來討論一下在Quartz里job的本質和job實例的生命周期。首先我們來看看第一節的代碼片段:

JobDetail jobDetail = new JobDetail(“myJob”, ?????// job 名稱

sched.DEFAULT_GROUP, // job組名(可以寫’null’來用default group)

DumbJob.class);??????? ?//要執行的java類

Trigger trigger = TriggerUtils.makeDailyTrigger(8, 30);

trigger.setStartTime(new Date());

trigger.setName(“myTrigger”);

sched.scheduleJob(jobDetail, trigger);

現在我們定義“DumbJob”類:

public class DumbJob implements Job {

public DumbJob() {

}

public void execute(JobExecutionContext context)

throws JobExecutionException

{

System.err.println(“DumbJob is executing.”);

}

}

可以看到我們給調度器一個JobDetail實例,并且,它通過job的類代碼引用這個job來執行。每次調度器執行job時,它會在調用job的execute(..)方法之前創建一個他的實例。這就帶來了兩個事實:一、job必須有一個不帶參數的構造器,二、在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);

jobDetail.getJobDataMap().put(“myStateData”, new ArrayList());

在job執行時,我們可以在job里通過如下代碼得到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.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再次進入調度器或者今后不再運行。

本站部分文章源于互聯網,本著傳播知識、有益學習和研究的目的進行的轉載,為網友免費提供。如有著作權人或出版方提出異議,本站將立即刪除。如果您對文章轉載有任何疑問請告之我們,以便我們及時糾正。

PS:推薦一個微信公眾號: askHarries 或者qq群:474807195,里面會分享一些資深架構師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高并發、高性能、分布式、微服務架構的原理,JVM性能優化這些成為架構師必備的知識體系。還能領取免費的學習資源,目前受益良多

轉載請注明原文出處:Harries Blog? » 【Quartz指南】更多關于Jobs & JobDetails

贊 (0)
分享到:更多 ()

評論 0

  • 昵稱 (必填)
  • 郵箱 (必填)
  • 網址
六合彩最高极限