Quartz作业 - 不允许在组范围内并发执行?

时间:2012-10-18 14:30:13

标签: quartz-scheduler

使用Quartz,我希望很少有工作(比如大约10个)作为一个链来执行 - 即不兼容。 它们应该在“会计日更改”事件发生后执行但由于它们都访问相同的数据库,我不希望它们一起启动。我希望它们顺序执行(顺序无关紧要)。

我有一个想法将它们放入一个组 - 比如说“account_day_change_jobs”并以某种方式配置Quartz为我做其余的事情:-)手段 - 按顺序运行组中的所有作业。我尝试了API文档(1.8和2.1),试过谷歌但没有找到任何东西。

有可能吗?它甚至合理吗?其他想法如何实现我想要的行为?

非常感谢任何想法:-) 汉斯

2 个答案:

答案 0 :(得分:0)

自从我使用石英以来已经很长时间了,但我会尝试两个job listeners注册来听两个不同的组

基本思想是从一个组/列表(“todayGroup”)中激活一个作业,'(“todayGroup”)作业监听器检测完成的好坏。然后开始列表中的下一个工作。但是,它将“刚刚完成”的作业保存在(“tomorrowGroup”)下的调度程序中。

public class MyTodayGroupListener extends JobListenerSupport {

    private String name;

    private static String GROUP_NAME = "todayGroup";

    public MyOtherJobListener(String name) {
    this.name = name;
    }

    public String getName() {
    return name;
    }


    @Override
    public void jobWasExecuted(JobExecutionContext context,
        JobExecutionException jobException) {
        Scheduler sched = context.getScheduler();
        // switch the job to the other group so we don't run it again today.
        JobDetail current = context.getJobDetail();
        JobDetail tomorrows  = current.getJobBuilder().withIdentity(current.getKey().getName(), "tomorrow").build();
        sched.addJob(tomorrows,true);

        //see if there is anything left to run
        Set<JobKey> jobKeys = sched.getJobKeys(groupEquals(GROUP_NAME ));
        Iterator<JobKey> nextJob = null;
        if(jobKeys != null && !jobKeys.isEmpty() ){
            nextJob = jobKeys.iterator();
        }
        if(nextJob != null){
            // Define a Trigger that will fire "now" and associate it with the first job from the list
            Trigger trigger = newTrigger()
                .withIdentity("trigger1", "group1")
                .startNow()
                .forJob(nextJob =.next())
                .build();

            // Schedule the trigger
            sched.scheduleJob(trigger);
        }

    }
}
同样地,你需要两个“群组触发器”,它们会在你想要的给定时间从各自的小组中解雇第一份工作。

答案 1 :(得分:0)

下面的Trigger Listener类应重新计划任何尝试执行的作业,而另一个已配置监听器的作业正在运行。 我只是对它进行了轻微的测试,但对于简单的情况,它应该是合适的。

public class SequentialTriggerListener extends TriggerListenerSupport {

private JobKey activeJob;
private Scheduler activeScheduler;
private Queue<JobDetail> queuedJobs = new ConcurrentLinkedQueue<JobDetail>();

public String getName() {
    return "SequentialTriggerListener";
}

public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
    synchronized (this) {
        if (activeJob != null) {
            getLog().debug("Queueing Sequential Job - " + context.getJobDetail().getKey().getName());
            JobDetail jd = context.getJobDetail();
            activeScheduler = context.getScheduler();
            jd = JobBuilder.newJob().usingJobData(jd.getJobDataMap()).withIdentity(getName() + ":" + jd.getKey().getName(), jd.getKey().getGroup())
                    .ofType(jd.getJobClass()).build();
            queuedJobs.add(jd);
            return true;
        } else {
            activeJob = trigger.getJobKey();
            getLog().debug("Executing Job - " + activeJob.getName());
            return false;
        }
    }
}

public void triggerMisfired(Trigger trigger) {
    triggerFinalized(trigger);
}

public void triggerComplete(Trigger trigger, JobExecutionContext context, CompletedExecutionInstruction triggerInstructionCode) {
    triggerFinalized(trigger);
}

protected void triggerFinalized(Trigger trigger) {
    synchronized (this) {
        try {
            if (trigger.getJobKey().equals(activeJob)) {
                getLog().debug("Finalized Sequential Job - " + activeJob.getName());
                activeJob = null;
                JobDetail jd = queuedJobs.poll();
                if (jd != null) {
                    getLog().debug("Triggering Sequential Job - " + jd.getKey().getName());
                    activeScheduler.scheduleJob(jd,TriggerBuilder.newTrigger().forJob(jd).withIdentity("trigger:" + jd.getKey().getName(), jd.getKey().getGroup())
                            .startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(0).withIntervalInMilliseconds(1)).build());
                }
            } else {
                // this should not occur as the trigger finalizing should be the one we are tracking.
                getLog().warn("Sequential Trigger Listener execution order failer");
            }
        } catch (SchedulerException ex) {
            getLog().warn("Sequential Trigger Listener failure", ex);
        }
    }

}

}