石英怪队列行为

时间:2017-06-12 13:02:27

标签: java quartz-scheduler

我有一个每个间隔运行的作业(对于下面的例子,3秒),有时可能需要超过间隔,在这种情况下,我希望它立即开始一项新工作并保持定期延迟(3秒)并且不会运行所有失误的工作。

在下面的示例中,我启动了一个每3秒执行一次作业的调度程序

第四份工作将睡15秒 这意味着5个工作岗位将被熄火并且在石英队列中

有一种奇怪的行为,我会尽力解释;

如果我使用默认配置启动StdSchedulerFactory,它将运行所有失效的作业 但如果我启动它并将“org.quartz.threadPool.threadCount”属性设置为数字> 0它不会全部失效(按要求工作),为什么会这样?

import org.quartz.DisallowConcurrentExecution;
import org.quartz.CronScheduleBuilder;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

import java.util.Date;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * synchronized job scheduler test;
 *      if job execution time took more than the interval then:
 *          - start new job right away
 *          - do not run misfired jobs
 *          - keep regular delay afterwards
 */
public class Main {

    private static final String CRON_EXPRESSION = "0/2 * * * * ?";
    private static final String GROUP_KEY = "group1";
    private static final String JOB_KEY = "job1";
    private static final String TRIGGER_KEY = "trigger1";

    // for logging purposes only
    private static AtomicInteger jobsCounter = new AtomicInteger(0);
    private static final String LOG_DATE_TIME_FORMAT = "HH:mm:ss";
    private static final DateFormat DF = new SimpleDateFormat(LOG_DATE_TIME_FORMAT);

    public static void main(String[] args) {
        JobKey jobKey = new JobKey(JOB_KEY, GROUP_KEY);
        JobDetail job = JobBuilder.newJob(CustomJob.class).withIdentity(jobKey).build();

        /*
         misfired job means job threw JobExecutionException
         in our case the job finish after the interval so none of this flags aren't helpful
            cronSchedule.withMisfireHandlingInstructionFireAndProceed()
                        .withMisfireHandlingInstructionIgnoreMisfires()
                        .withMisfireHandlingInstructionDoNothing()
         */
        CronScheduleBuilder cronSchedule = CronScheduleBuilder.cronSchedule(CRON_EXPRESSION);
        TriggerKey triggerKey = new TriggerKey(TRIGGER_KEY, GROUP_KEY);
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronSchedule).build();

        try {
            Properties props = new Properties();
            // default configuration
            props.put("org.quartz.threadPool.threadCount", "10");
            props.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");
            props.put("org.quartz.scheduler.rmi.proxy", "false");
            props.put("org.quartz.scheduler.instanceName", "DefaultQuartzScheduler");
            props.put("org.quartz.scheduler.wrapJobExecutionInUserTransaction", "false");
            props.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
            props.put("org.quartz.jobStore.class", "org.quartz.simpl.RAMJobStore");
            props.put("org.quartz.threadPool.threadPriority", "5");
            /**
             org.quartz.jobStore.misfireThreshold
             The the number of milliseconds the scheduler will ‘tolerate’ a trigger to pass its next-fire-time by,
             before being considered “misfired”.
             The default value (if you don’t make an entry of this property in your configuration) is 60000 (60 seconds).
             */
            // FIXME UNDERSTAND STRANGE BEHAVIOR
//            props.put("org.quartz.jobStore.misfireThreshold", "9100"); // this will execute all the jobs in queue when job wake up
            props.put("org.quartz.jobStore.misfireThreshold", "8900"); // this will execute once and continue as requested

            /**
             * strange behavior HERE if we initiate StdSchedulerFactory with default c'tor
             * Scheduler scheduler = new StdSchedulerFactory().getScheduler();
             */
            Scheduler scheduler = new StdSchedulerFactory(props).getScheduler();
//            Scheduler scheduler = new StdSchedulerFactory().getScheduler();
            scheduler.start();
            scheduler.scheduleJob(job, trigger);
        }
        catch (SchedulerException e) {
            System.err.println(e.getMessage());
        }
    }

    @DisallowConcurrentExecution // based upon JobKey
    public static class CustomJob implements Job { // must be public for quartz to start

        int jid; // job id, incremental

        public CustomJob() {
            jid = jobsCounter.incrementAndGet();
            log("c'tor");
        }

        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            try {
                log("start");
                // sleep for 15 seconds at job #4
                if (jid == 4) {
                    log("* sleep *");
                    Thread.sleep(11 * 1_000);
                }
                log("end");
            } catch (InterruptedException ignored) {}
        }

        private void log(String s) {
            String curTime = DF.format(new Date());
            StringBuffer sb = new StringBuffer().append(curTime).append("\t#").append(jid).append("\t").append(s);
            System.out.println(sb);
        }
    }

}

0 个答案:

没有答案