關於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>