2011-01-28 140 views
1

我正在使用Quartz Enterprise Job Scheduler(1.8.3)。作業配置來自多個xml文件,我們有一個特殊的作業可以檢測這些xml文件中的更改並重新計劃作業。這很有用,但問題是我還需要這個「調度程序作業」重新調度自己。一旦這項工作重新安排自己,出於某種原因,我看到它被執行了很多次。但我沒有看到任何例外。Quartz Enterprise Scheduler:計劃自己的作業

我已經複製並隔離了這個問題。這將是入口點:

public class App { 
    public static void main(final String[] args) throws ParseException, SchedulerException { 
    // get the scheduler from the factory 
    final Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); 

    // start the scheduler 
    scheduler.start(); 

    // schedule the job to run every 20 seconds 
    final JobDetail jobDetail = new JobDetail("jobname", "groupname", TestJob.class);   
    final Trigger trigger = new CronTrigger("triggername", "groupname", "*/20 * * * * ?"); 

    // set the scheduler in the job data map, so the job can re-configure itself 
    jobDetail.getJobDataMap().put("scheduler", scheduler); 

    // schedule job 
    scheduler.scheduleJob(jobDetail, trigger); 

    } 
} 

,這將是作業類:

public class TestJob implements Job { 

private final static Logger LOG = Logger.getLogger(TestJob.class); 
private final static AtomicInteger jobExecutionCount = new AtomicInteger(0); 

public void execute(final JobExecutionContext context) throws JobExecutionException { 
    // get the scheduler from the data map 
    final Scheduler scheduler = (Scheduler) context.getJobDetail().getJobDataMap().get("scheduler"); 
    LOG.info("running job! " + jobExecutionCount.incrementAndGet()); 

    // buid the job detail and trigger 
    final JobDetail jobDetail = new JobDetail("jobname", "groupname", TestJob.class); 
    // this time, schedule it to run every 35 secs 
    final Trigger trigger; 
    try { 
     trigger = new CronTrigger("triggername", "groupname", "*/50 * * * * ?"); 
    } catch (final ParseException e) { 
     throw new JobExecutionException(e); 
    } 
    trigger.setJobName("jobname"); 
    trigger.setJobGroup("groupname"); 

    // set the scheduler in the job data map, so this job can re-configure itself 
    jobDetail.getJobDataMap().put("scheduler", scheduler); 

    try { 
     scheduler.rescheduleJob(trigger.getName(), jobDetail.getGroup(), trigger); 
    } catch (final SchedulerException e) { 
     throw new JobExecutionException(e); 
    } 
} 
} 

我已經scheduler.rescheduleJobscheduler.deleteJob然後scheduler.scheduleJob都嘗試。無論我做什麼,這是我的輸出得到(我使用log4j的):

23:22:15,874   INFO SchedulerSignalerImpl:60 - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl 
23:22:15,878   INFO QuartzScheduler:219 - Quartz Scheduler v.1.8.3 created. 
23:22:15,883   INFO RAMJobStore:139 - RAMJobStore initialized. 
23:22:15,885   INFO QuartzScheduler:241 - Scheduler meta-data: Quartz Scheduler (v1.8.3) 

'MyScheduler' with instanceId '1' 
    Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally. 
    NOT STARTED. 
    Currently in standby mode. 
    Number of jobs executed: 0 
    Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads. 
    Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered. 

23:22:15,885   INFO StdSchedulerFactory:1275 - Quartz scheduler 'MyScheduler' initialized from default resource file in Quartz package: 'quartz.properties' 
23:22:15,886   INFO StdSchedulerFactory:1279 - Quartz scheduler version: 1.8.3 
23:22:15,886   INFO QuartzScheduler:497 - Scheduler MyScheduler_$_1 started. 
23:22:20,018   INFO TestJob:26 - running job! 1 
23:22:50,004   INFO TestJob:26 - running job! 2 
23:22:50,010   INFO TestJob:26 - running job! 3 
23:22:50,014   INFO TestJob:26 - running job! 4 
23:22:50,016   INFO TestJob:26 - running job! 5 
... 
23:22:50,999   INFO TestJob:26 - running job! 672 
23:22:51,000   INFO TestJob:26 - running job! 673 

注意如何在23:22:20018,工作運行良好。此時,作業重新安排自己每隔50秒運行一次。下次運行(23:22:50,004)時,它會安排數百次。

關於如何配置作業的任何想法執行該作業?我究竟做錯了什麼?

謝謝!

回答

5

簡單。

首先,您對Cron Expressions有一些誤解。 「*/20 * * * *?」是每20秒,因爲評論暗示,但只是因爲60可以被20整除。「/50 ...」不是每五十秒。它是每分鐘0和50秒。作爲另一個例子,「/13 ...」是每分鐘的0,13,26,39和52秒 - 因此在第二秒52和下一分鐘的0秒之間,僅有8秒而不是13秒。因此,對於*/50你會在其他所有射擊之間得到50秒,而在其他射擊之間得到10秒。

然而,這不是你快速解僱工作的原因。問題在於目前的秒數是「50」,並且你正在安排新的觸發器在第二個「50」上發射,所以它立即發射。然後它仍然是第二個50,並且這個工作再次執行,並且它在另一個50上安排另一個觸發器以等待50次,等等。

您需要將觸發器的開始時間設置爲將來(至少一秒),或者如果日程表與當前時間匹配,它將在您安排它的同一秒內觸發。

此外,如果你真的需要每個「N」秒的時間表類型,我建議SimpleTrigger而不是CronTrigger。 SimpleTrigger可以做「每35秒」或「每50秒」沒有問題。 CronTrigger適用於表達式,如「在1月的每個星期一10點鐘的15分鐘和45分鐘秒0,15,40和43秒」。

+0

是有道理的,我改變了測試應用程序的代碼,它現在的行爲如我所料......非常感謝 – chahuistle 2011-01-29 18:26:07