少年阿賓

          那些青春的歲月

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks
          1、StatefulJob
          implements StatefulJob使Job成為有狀態(tài)的,順序執(zhí)行 
          同一個有狀態(tài)的job實例不存在并發(fā),無狀態(tài)的job的并發(fā)數(shù)由上面配置的線程數(shù)決定。不想并發(fā)的話,設(shè)置成1,第二個線程在前一個執(zhí)行完以后觸發(fā)執(zhí)行。
          線程數(shù)大于1時,如果存在空閑線程,則到執(zhí)行時間點即觸發(fā)執(zhí)行。

          2、
          MethodInvokingJobDetailFactoryBean
          MethodInvokingJobDetailFactoryBean的并發(fā)問題
          大家在使用quartz的時候,一般只設(shè)置了“targetObject”和“targetMethod”,MethodInvokingJobDetailFactoryBean類默認(rèn)是并發(fā)執(zhí)行的,這時候如果不設(shè)置“concurrent”為false,很可能帶來并發(fā)或者死鎖的問題,而且?guī)茁瘦^小,不容易復(fù)現(xiàn),請大家使用的時候注意設(shè)置“concurrent”。
           
              <bean id="cpm.MessageJobFactoryBean" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
                  <property name="targetObject" ref="cpm.MessageJob"/>
                  <property name="targetMethod" value="execute"/>
                  <property name="concurrent" value="false"/>
              </bean>
          concurrent   同時發(fā)生
           concurrent:對于相同的JobDetail,當(dāng)指定多個Trigger時, 很可能第一個job完成之前,第二個job就開始了。
           定concurrent設(shè)為false,多個job不會并發(fā)運行,第二個job將不會在第一個job完成之前開始




          防止job并行運行的幾種解決方案 
          一、JOB State 
          在通過MethodInvokingJobDetailFactoryBean在運行中動態(tài)生成的Job,配置的xml文件有個concurrent屬性,表示job是否可以并行運行:如果一個job的業(yè)務(wù)處理發(fā)費的時間超過了job的啟動的間隔時間(repeatInterval),這個屬性非常有用。如果為false,那么,在這種情況下,當(dāng)前job還在運行,那么下一個job只能延時運行。如果為true,那么job就會并行運行。在實際的應(yīng)用中應(yīng)該配置為true/false,要根據(jù)需要了(廢話)。 
          二、如果通過繼承QuartzJobBean實現(xiàn)job的話,默認(rèn)情況下QuartzJobBean是implements org.quartz.Job接口的,也就是說job示例是stateless的,會出現(xiàn)前面所述的并行情況。而代碼中卻要求job任務(wù)必需串行,解決辦法:在job子類中繼續(xù)implements org.quartz.StatefulJob。那么這個job實例變成了Stateful,job任務(wù)也就是串行的了。
          注: 
          在Quartz中,如果實現(xiàn)org.quartz.Job接口,那么這個job是stateless的,job實例的參數(shù)不能在多個任務(wù)之間共享,如果實現(xiàn)org.quartz.StatefulJob,這個job是個單例的,job實例的屬性可以從當(dāng)前任務(wù)傳遞到下一個任務(wù)。 


          spring和quartz的整合對版本是有要求的。
          spring3.1以下的版本必須使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然會出錯。

          至于原因,則是spring對于quartz的支持實現(xiàn),org.springframework.scheduling.quartz.CronTriggerBean繼承了org.quartz.CronTrigger,在quartz1.x系列中org.quartz.CronTrigger是個類,而在quartz2.x系列中org.quartz.CronTrigger變成了接口,從而造成無法用spring的方式配置quartz的觸發(fā)器(trigger)。

          在Spring中使用Quartz有兩種方式實現(xiàn):第一種是任務(wù)類繼承QuartzJobBean,第二種則是在配置文件里定義任務(wù)類和要執(zhí)行的方法,類和方法可以是普通類。很顯然,第二種方式遠(yuǎn)比第一種方式來的靈活。



          MethodInvokingJobDetailFactoryBean中concurrent和shouldRecover屬性的作用
          解釋 concurrent為true,則允許一個QuartzJob并發(fā)執(zhí)行,否則就是順序執(zhí)行。例如QuartzJob A執(zhí)行時間為15秒,配置為每10秒執(zhí)行一次;如果concurrent為true,則0秒的時候啟動一次A,10秒的時候再啟動一次A,20秒的時候再啟動一次A,不管前面啟動的A有沒有執(zhí)行完;如果concurrent為false,則0秒的時候啟動一次A,15秒的時候A執(zhí)行完畢,再第二次啟動A。
          shouldRecover屬性為true,則當(dāng)Quartz服務(wù)被中止后,再次啟動或集群中其他機(jī)器接手任務(wù)時會嘗試恢復(fù)執(zhí)行之前未完成的所有任務(wù)。例如QuartzJob B,在每次00秒的時候啟動,假如在03:00的任務(wù)執(zhí)行完之后服務(wù)器1被中止,服務(wù)器2在05:15的時候才接手;如果shouldRecover屬性為true,則服務(wù)器2會嘗試著補回原來在04:00和05:00的時候應(yīng)該做的任務(wù),如果shouldRecover屬性為false,則服務(wù)器2只會從06:00的時候再執(zhí)行B。


          Quartz集群只支持JDBCJobStore存儲方式,而MethodInvokingJobDetailFactoryBean不能序列化存儲job數(shù)據(jù)到數(shù)據(jù)庫,
          重寫 quartz 的 QuartzJobBean 類 
          原因是在使用 quartz+spring 把 quartz 的 task 實例化進(jìn)入數(shù)據(jù)庫時,會產(chǎn)生: serializable 的錯誤,原因在于:
          這個 MethodInvokingJobDetailFactoryBean 類中的 methodInvoking 方法,是不支持序列化的,因此在把 QUARTZ 的 TASK 序列化進(jìn)入數(shù)據(jù)庫時就會拋錯。網(wǎng)上有說把 SPRING 源碼拿來,修改一下這個方案,然后再打包成 SPRING.jar 發(fā)布,這些都是不好的方法,是不安全的。
          必須根據(jù) QuartzJobBean 來重寫一個自己的類 。


          posted on 2015-07-26 01:39 abin 閱讀(2128) 評論(0)  編輯  收藏 所屬分類: quartz
          主站蜘蛛池模板: 海宁市| 安吉县| 田林县| 通化市| 临沭县| 马山县| 仁怀市| 宁城县| 林周县| 锡林浩特市| 忻州市| 漳州市| 和政县| 大荔县| 北川| 南木林县| 皮山县| 绥阳县| 湖北省| 长泰县| 海门市| 错那县| 泉州市| 句容市| 玉龙| 邹城市| 内丘县| 苍溪县| 肥东县| 平凉市| 普宁市| 湾仔区| 龙岩市| 元阳县| 汉沽区| 平和县| 上杭县| 萍乡市| 遂川县| 定陶县| 社旗县|