小编典典

石英:在Jobs.xml中阻止作业的并发实例

java

这应该真的很容易。我使用的是在Apache Tomcat
6.0.18下运行的Quartz,我有一个jobs.xml文件,该文件设置了每分钟运行的计划作业。

我想做的是,如果下一个触发时间到来时该作业仍在运行,则我不想启动新作业,因此可以让旧实例完成。

有没有办法在Jobs.xml中指定此设置(防止并发实例)?

如果不是,是否可以共享我的应用程序Job实现中对内存中单例的访问(这是通过JobExecutionContext吗?),以便我自己处理并发性?(并检测以前的实例是否正在运行)


更新: 在文档中苦苦挣扎之后,我正在考虑以下两种方法,但是要么不知道如何使它们工作,要么有问题。

  1. 使用StatefulJob。这样可以防止并发访问…但是我不确定如果使用它,还会产生其他副作用,我也想避免以下情况:

假设触发时间是每分钟,即触发#0 =在时间0,触发#1 = 60000msec,触发#2 = 120000,#3 =
180000,依此类推,触发在时间0的触发#0触发了我的工作,耗时130000msec。对于普通作业,它将在作业触发器#0仍在运行时执行触发器#1和#2。使用StatefulJob,它将在#0在130000之后完成后立即执行触发器#1和#2。我不希望那样,我不希望#1和#2运行,而下一个运行作业的触发器应该发生在#3(180000msec)。因此,我仍然必须对StatefulJob进行其他操作才能使其按我想要的方式工作,因此使用它并没有太大优势。

  1. 使用TriggerListener从vetoJobExecution()返回true。

尽管实现接口似乎很简单,但我必须弄清楚如何以声明方式设置一个TriggerListener实例。
3. 使用static实现Job的类拥有的共享线程安全对象(例如,信号量或其他)。

我不喜欢通过staticTomcat /
Quartz下的关键字使用单例的想法,不确定是否有副作用。另外,我真的不希望它们成为真正的单例,而只是与特定工作定义相关联的东西。

  1. 实现我自己的触发器,该触发器扩展了SimpleTrigger并包含可以运行自己的TriggerListener的共享状态。

同样,我不知道如何设置XML文件以使用此触发器而不是使用standard
<trigger><simple>...</simple></trigger>


阅读 214

收藏
2020-10-18

共1个答案

小编典典

当您的Quartz作业唤醒时,您可以执行以下操作:

JobDetail existingJobDetail = sched.getJobDetail(jobName, jobGroup);
    if (existingJobDetail != null) {
        List<JobExecutionContext> currentlyExecutingJobs = (List<JobExecutionContext>) sched.getCurrentlyExecutingJobs();
        for (JobExecutionContext jec : currentlyExecutingJobs) {
            if(existingJobDetail.equals(jec.getJobDetail())) {
                //String message = jobName + " is already running.";
                //log.info(message);
                //throw new JobExecutionException(message,false);
            }
        }
        //sched.deleteJob(jobName, jobGroup); if you want to delete the scheduled but not-currently-running job
    }
2020-10-18