quartz在job間隔期間內,保證上一個任務執行完後,再去排程下一個任務(轉),在多執行緒情況下的問題

天才小熊貓寶寶發表於2018-01-30

Quartz定時任務預設都是併發執行的,不會等待上一次任務執行完畢,只要間隔時間到就會執行,這樣往往會導致我們執行的資料不正確。如果定時任執行太長,會長時間佔用資源,導致其它任務堵塞。

解決辦法:

1.在Spring中這時需要設定concurrent的值為false, 禁止併發執行。

 <property name="concurrent" value="true" />

2.當不使用spring的時候就需要在Job的實現類上加@DisallowConcurrentExecution的註釋

        @DisallowConcurrentExecution 禁止併發執行多個相同定義的JobDetail, 這個註解是加在Job類上的, 但意思並不是不能同時執行多個Job, 而是不能併發執行同一個Job Definition(由JobDetail定義), 但是可以同時執行多個不同的JobDetail, 舉例說明,我們有一個Job類,叫做SayHelloJob, 並在這個Job上加了這個註解, 然後在這個Job上定義了很多個JobDetail, 如sayHelloToJoeJobDetail, sayHelloToMikeJobDetail, 那麼當scheduler啟動時, 不會併發執行多個sayHelloToJoeJobDetail或者sayHelloToMikeJobDetail, 但可以同時執行sayHelloToJoeJobDetail跟sayHelloToMikeJobDetail

       @PersistJobDataAfterExecution 同樣, 也是加在Job上,表示當正常執行完Job後, JobDataMap中的資料應該被改動, 以被下一次呼叫時用。當使用@PersistJobDataAfterExecution 註解時, 為了避免併發時, 儲存資料造成混亂, 強烈建議把@DisallowConcurrentExecution註解也加上。


(但是這樣會導致任務的執行不是按照我們預先定義的時間間隔執行)

----------華麗的分割線,以上是轉發別人的內容---------------------

我親自試了加上了@DisallowConcurrentExecution 這個註解,結果發現完全沒有任何效果,為什麼呢,於是懷著疑問我又寫了一個簡單的job排程,結果我測試的結果大大的出乎我的意料,測試的過程這裡就不描述了,這裡告訴大家我的結果,不信的同學可以去試試。

結果:如果job裡面用多執行緒操作的,那麼會讓這個註釋失效,因為這個註釋是改變狀態,而多執行緒會使狀態無效,如果你想要排程任務,又想使用多執行緒(即同一個排程(觸發器)呼叫多個job),建議和我一樣把多執行緒的部分提到前面啟動哪一個部分。這樣就可以具備多執行緒又可以使得註釋有效。

相關文章