honzeland

          記錄點滴。。。

          常用鏈接

          統計

          Famous Websites

          Java

          Linux

          P2P

          最新評論

          Quartz scheduled executions

          這周被Quartz折騰了一番。
          我們知道,Quartz采用JobDataMap實現向Job實例傳送配置屬性,正如Quartz官方文檔說的那樣:

          How can I provide properties/configuration for a Job instance? The key is the JobDataMap, which is part of the JobDetail object.
          The JobDataMap can be used to hold any number of (serializable) objects which you wish to have made available to the job instance when it executes.
          JobDataMap map = context.getJobDetail().getJobDataMap();

          我們通過map向Job實例傳送多個objects,其中有一個是個bean,一個是基本類型。對于scheduled triggers,我們要求bean對于所有的序列都不變,包括其屬性,而基本類型可以在Job運行過程中改變,并影響下一個序列。實際情況是,對于下個序列,bean的屬性被上次的修改了,而基本類型卻維持第一次put到Map里面的值。正好和我們要求的相反。

          受bean的影響,以為map里面包含的都是更新的對象,即每個序列里面的JobDetail是同一個對象,但是基本類型的結果否認了這一點。回頭重新翻閱了下Quartz的文檔:

          Now, some additional notes about a job's state data (aka JobDataMap): A Job instance can be defined as "stateful" or "non-stateful". Non-stateful jobs only have their JobDataMap stored at the time they are added to the scheduler. This means that any changes made to the contents of the job data map during execution of the job will be lost, and will not seen by the job the next time it executes.

          Job有兩個子接口:StatefulJob and InterruptableJob,我們繼承的是InterruptableJob,或許Quartz應該有個InterruptableStatefulJob。另外StatefulJob不支持并發執行,和我們的需求不匹配,我們有自己的同步控制,Job必須可以并發運行。

          然后查看了Quartz的相關源碼:

          // RAMJobStore.storeJob
          public void storeJob(SchedulingContext ctxt, JobDetail newJob,
                      
          boolean replaceExisting) throws ObjectAlreadyExistsException {
                  JobWrapper jw 
          = new JobWrapper((JobDetail)newJob.clone()); // clone a new one
                  .
                  jobsByFQN.put(jw.key, jw);
                  
          }

          也就是說,store里面放的是初始JobDetail的克隆,在序列運行完時,只有StatefulJob才會更新store里面的JobDetail:

          // RAMJobStore.triggeredJobComplete
          public void triggeredJobComplete(SchedulingContext ctxt, Trigger trigger,
                      JobDetail jobDetail, 
          int triggerInstCode) {
              JobWrapper jw 
          = (JobWrapper) jobsByFQN.get(jobKey);
              
              
          if (jw != null) {
                  JobDetail jd 
          = jw.jobDetail;
                  
          if (jd.isStateful()) {
                      JobDataMap newData 
          = jobDetail.getJobDataMap();
                      
          if (newData != null) {
                          newData 
          = (JobDataMap)newData.clone();
                          newData.clearDirtyFlag();
                      }
                      jd.setJobDataMap(newData); 
          // set to new one
                      
                  
              }

          }



          然后,每次序列運行時所用的JobDetail,是存放在Store里面的克隆。

          // RAMJobStore.retrieveJob
          public JobDetail retrieveJob(SchedulingContext ctxt, String jobName,
                  String groupName) {
              JobWrapper jw 
          = (JobWrapper) jobsByFQN.get(JobWrapper.getJobNameKey(
                  jobName, groupName));
              
          return (jw != null? (JobDetail)jw.jobDetail.clone() : null// clone a new
          }


          問題很清楚了,存放在Store里面的JobDetail是初始對象的克隆,然后每個序列所用的JobDetail, 是Store里面的克隆,只有Stateful job,Store里面的JobDetail才更新。
          最有Quartz里面使用的clone():

          // Shallow copy the jobDataMap.  Note that this means that if a user
          // modifies a value object in this map from the cloned Trigger
          // they will also be modifying this Trigger.
          if (jobDataMap != null) {
              copy.jobDataMap 
          = (JobDataMap)jobDataMap.clone();
          }


          所以對于前面所講的,修改bean的屬性,會影響所有clone的對象,因此,我們可以將基本類型封裝到一個bean里面,map里面存放的是bean,然后通過修改bean的屬性,來達到影響下一個序列的目的。

          posted on 2010-01-21 17:38 honzeland 閱讀(414) 評論(0)  編輯  收藏 所屬分類: Java

          主站蜘蛛池模板: 武隆县| 土默特右旗| 贵南县| 肇庆市| 新和县| 苏州市| 颍上县| 建始县| 瑞昌市| 交城县| 常熟市| 措美县| 富平县| 东莞市| 綦江县| 额济纳旗| 扶风县| 滨州市| 宽甸| 慈利县| 阿瓦提县| 灌阳县| 锡林郭勒盟| 苏尼特左旗| 林周县| 新建县| 年辖:市辖区| 仙桃市| 和田市| 台北县| 临安市| 新建县| 聊城市| 邵武市| 古田县| 石家庄市| 安图县| 屏边| 枣强县| 美姑县| 兴业县|