1. 程式人生 > >關於Spring中用quartz定時器在定時到達時同時執行兩次的問題

關於Spring中用quartz定時器在定時到達時同時執行兩次的問題

我在使用spring的quartz配置定時任務時,發現每次定時時間到達後,指定的定時方法同時執行兩次,而且此方法還是使用的synchronized關鍵字,每次定時一到,會發現此方法內的System.out輸出資訊輸出兩次,說明方法在這時執行了兩次,解決方法沒有找到更好的,不過有一個方法很有效,我設定了一個靜態變數,只要此方法一執行,就將變數由0變為1,執行完再設定為0.如果執行方法前檢查此靜態變數不為0,則return.開發時注意此靜態變數不要讓別的方法使用.

下面是定時相關的程式碼:

package org.openjweb.core.schedule;

 
import org.apache.log4j.Logger;
import org.apache.lucene.demo.IndexHTML;
//import org.apache.lucene.demo.IndexHTML;
import org.openjweb.core.service.ServiceLocator;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class JobSchedule extends QuartzJobBean
{
 static Logger logger = Logger.getLogger(JobSchedule.class);
 static long counter = 0;  //計數器
 //static long priorTime = System.currentTimeMillis();
 static int searchIndexFlag =0;//由doBuildIndex修改,其他方法不要修改此引數
 
 public synchronized void doTimerSchedule()
 {
  counter++;
  //System.out.println("測試定時器,總計數:"+String.valueOf(counter));
 }

 protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
  // TODO Auto-generated method stub

 }
 
 
 public synchronized void doBuildIndex()
 {
  //定時器同時呼叫兩次的問題需要查詢原因
  if(searchIndexFlag>0)return ;//保證同一時刻只有一個定時器執行,通過這種方式保證每次定時時間到時,只執行一個執行緒
  searchIndexFlag = 1;//鎖定
  System.out.println("開始構造索引庫....");
     String indexPath = ServiceLocator.getSysConfigService().getStringValueByParmName("luceneIndexDir");
  String filePath = ServiceLocator.getSysConfigService().getStringValueByParmName("searchRoot");
  System.out.println("索引路徑為:"+indexPath);
  System.out.println("搜尋路徑為:"+filePath);
  
  IndexHTML.buildIndex(indexPath,filePath);
  System.out.println("索引庫構造完畢!");
  searchIndexFlag = 0;//鎖定解除
 }

}

使用靜態變數標誌的方式解決了同一時刻呼叫兩次方法的問題,但我想Spring應該有辦法配置只能同一時刻執行一次,是什麼造成的定時執行兩次呢?大家有沒有發現這種問題,歡迎賜教.下面是我在spring的配置:

  <!-- Timer schedule -->
    <bean id="defaultTimerBean" class="org.openjweb.core.schedule.JobSchedule"/>
    <bean id="defaultTimerMethod" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="defaultTimerBean" />
        <property name="targetMethod" value="doTimerSchedule" />
        <property name="concurrent" value="false" /> <!--將併發設定為false-->
    </bean>
    <bean id="defaultTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="defaultTimerMethod" />
        <!--每三分鐘的第一分鐘觸發-->
        <property name="cronExpression" value="0 1/3 * * * ?" />
    </bean>
   
    <bean id="luceneTimerMethod" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="defaultTimerBean" />
        <property name="targetMethod" value="doBuildIndex" />
        <property name="concurrent" value="false" /> <!--將併發設定為false-->
    </bean>
    <bean id="luceneTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="luceneTimerMethod" />
        
        <property name="cronExpression" value="0 1/4 * * * ?" />
    </bean>
   
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <!--作業排程器,list下可加入其他的排程器-->
                <ref bean="defaultTrigger"/>
                <ref bean="luceneTrigger"/> 
            </list>
        </property>
    </bean>