Quartz,每次執行job,job永遠是全新的對象,但是,如果job實現org.quartz.StatefulJob接口,而不是job接口.
此時JobDetail的JobDataMap將會共享一個對象。
注意:
當實現有狀態接口,StatefulJob時,只有JobDetail的JobDataMap是共用的,其他的,比如,Job本身,Trigger等,仍然每次執行
的時候是全新的對象。所以,只有JobDetail的JobDataMap是共用的,其他的trigger.getJobDataMap(),context.getMergedJobDataMap(),等這些JobDataMap,任然是全新的
以下引用文檔:
使用有狀態的 Job
當你需要在兩次 Job 執行間維護狀態的話,Quartz 框架為此提供了 org.quartz.StatefulJob 接口。StatefulJob 接口僅僅是擴展了 Job 接口,未加入新的方法。你只需要通過使用與 Job 接口相同的 execute() 方法簡單的實現 StatefulJob 接口即可。假如你有已存在的 Job 類,你所有要做的只是改變 Job 的接口為 org.quartz.StatefulJob。
Job 和 StatefulJob 在框架中使用中存在兩個關鍵差異。首先,JobDataMap 在每次執行之后重新持久化到 JobStore 中。這樣就確保你對 Job 數據的改變直到下次執行仍然保持着。
改變有狀態 Job 的 JobDataMap 你可以在有狀態 Job 中簡單的通過 map 的 put() 方法來修改 JobDataMap.已存在的任何數據會被新的數據覆蓋掉。你也能對無狀態的 Job 這么做,但是因為對於無狀態 Job 來說,JobDataMap 不會持久化,所以數據不會保存下來。對於 Trigger 和 JobExecutionContext 上的 JobDataMap 的數據修改也是沒能保存下來的。 |
另 一個無狀態和有狀態 Job 重大區別就是:兩個或多個有狀態的 JobDetail 實例不能並發執行。說的是你創建並注冊了一個有狀態 JobDetail 到 Scheduler 上。你還建立了兩個 Trigger 來觸發這個 Job:一個每五分鍾觸發,另一個也是每五分釧觸發。假如這兩個 Trigger 試圖在同一時刻觸發 Job,框架是不允許這種事情發生的。第二個 Trigger 一直會被阻塞直到第一個結束。
這就產生了處理 JobDataMap 存儲的需求了。因為 JobDataMap 的存儲是伴隨着 JobDetail 的,而 JobDetail 定義了 Job 實例,所以線程安全性問題必須納入到我們考慮的范疇。同一時刻只能由一個線程去運行並更新 JobDataMap 存儲。然而,由於在第一個 Trigger 有機會更新存儲之前第二個就會試圖執行 Job,所以數據有可能會出錯。甚至可能的話還會第二個 Trigger 先於第一個執行完成(依賴於你的 Job 所做的事情),這時就可能會出現奇怪的結果。
因為這些區別,在你使用 StatefulJob 時可要謹慎了。當你需要避免並發執行一個 Job 時,那么有狀態 Job 就是你最簡單的籌碼了。在 J2EE 的世界里,有狀態一詞已經引起了一些負面影響,但對於 Quartz 卻非如此。