首页 文章

Quartz Enterprise Scheduler:自行安排的作业

提问于
浏览
1

我正在使用Quartz Enterprise Job Scheduler(1.8.3) . 作业配置来自几个xml文件,我们有一个特殊的作业,可以检测这些xml文件中的更改并重新计划作业 . 这很有用,但问题是我还需要这个“调度程序工作”来重新安排自己 . 一旦这个工作重新安排自己,由于某种原因,我看到它被执行了很多次 . 不过,我没有看到任何例外 .

我已经复制并隔离了这个问题 . 这将是切入点:

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:20,018,这项工作运行良好 . 此时,作业重新安排自己每隔50秒运行一次 . 下次运行时(23:22:50,004),它会被安排数百次 .

有关如何在执行该作业时配置作业的任何想法?我究竟做错了什么?

谢谢!

1 回答

  • 5

    简单 .

    首先,你对Cron Expressions有一些误解 . "*/20 * * * * ?"是评论所暗示的每20秒,但仅仅因为60可被20整除 . “/ 50 ... " is not every fifty seconds. it is seconds 0 and 50 of every minute. As another example, " / 13 ......”是每分钟的0,13,26,39和52秒 - 所以在第二个52和下一个分钟之间's 0 second, there is only 8 seconds, not 13. So with */50 you' ll在每次其他射击之间获得50秒,在其他射击之间获得10秒 .

    然而,这并不是你快速解雇工作的原因 . 问题是当前秒是“50”并且您正在安排新触发器在第二个“50”上触发,因此它会立即触发 . 然后它仍然是第二个50,并且作业再次执行,它会安排另一个触发器在第二个50上触发,依此类推,在第50个秒内可以多次触发 .

    如果计划与当前秒匹配,则需要将触发器的开始时间设置为将来(至少一秒),否则它将在您安排它的同一秒启动 .

    此外,如果你真的需要每个“N”秒类型的时间表,我建议使用SimpleTrigger而不是CronTrigger . SimpleTrigger可以“每35秒”或“每50秒”做一次没问题 . CronTrigger适用于“在1月的每个星期一的10点钟的15和45分钟的0,15,40和43秒”这样的表达 .

相关问题