quartz:防止jobs.xml中的作业的并发实例 [英] quartz: preventing concurrent instances of a job in jobs.xml

查看:219
本文介绍了quartz:防止jobs.xml中的作业的并发实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这应该很容易。我使用Quartz在Apache Tomcat 6.0.18下运行,我有一个工作



我想做的是,如果作业仍在运行,当下一个触发时间滚动,我不想开始一个新的工作,所以我可以让老实例完成。



是否有办法在工作中指定。如果没有,是否有一种方式,我可以共享访问内存中的单例在我的应用程序的

< /www.quartz-scheduler.org/docs/api/org/quartz/Job.htmlrel =nofollow noreferrer> Job
实现(就是通过 JobExecutionContext ?)所以我可以自己处理并发? (并检测上一个实例是否正在运行)






更新: docs,这里有一些我正在考虑的方法,但是不知道如何让他们工作,或有问题。


  1. 使用 StatefulJob 。这防止并发访问...但我不知道如果我使用它会发生什么其他副作用,我想避免以下情况:



    假设触发时间将是每分钟,即触发#0 =在时间0,触发#1 = 60000msec,#2 = 120000,#3 = 180000等,并且在时间0的触发器#0触发我的工作,这需要130000msec。使用纯作业,当作业触发器#0仍在运行时,将执行触发器#1和#2。使用StatefulJob,这将按顺序执行触发器#1和#2,在#0在130000完成后立即执行。我不想要,我想#1和#2不运行,并且运行作业的下一个触发器发生在#3(180000毫秒)。所以我还是要用StatefulJob做其他事情,让它以我想要的方式工作,所以我没有看到使用它的优势。


  2. p>使用 TriggerListener 从vetoJobExecution返回true ()。



    虽然实现接口看起来很简单,但我必须找出如何以声明方式设置一个TriggerListener实例。 找不到xml文件的文档


  3. 使用我的实现Job的类拥有的 static 共享线程安全对象(例如信号量或其他)。



    我不喜欢通过Tomcat / Quartz下的 static 关键字使用单例的想法,不知道是否有side效果。


  4. 实现我自己的触发,它扩展了 SimpleTrigger ,并且包含可以运行其自己的TriggerListener的共享状态。



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



解决方案Quartz工作唤醒你可以做:

  JobDetail existingJobDetail = sched.getJobDetail(jobName,jobGroup); 
if(existingJobDetail!= null){
List< JobExecutionContext> currentExecutingJobs =(List< JobExecutionContext>)sched.getCurrentlyExecutingJobs();
for(JobExecutionContext jec:currentlyExecutingJobs){
if(existingJobDetail.equals(jec.getJobDetail())){
//字符串message = jobName +已经在运行。
//log.info(message);
// throw new JobExecutionException(message,false);
}
}
//sched.deleteJob(jobName,jobGroup);如果要删除计划但不是当前运行的作业
}


This should be really easy. I'm using Quartz running under Apache Tomcat 6.0.18, and I have a jobs.xml file which sets up my scheduled job that runs every minute.

What I would like to do, is if the job is still running when the next trigger time rolls around, I don't want to start a new job, so I can let the old instance complete.

Is there a way to specify this in jobs.xml (prevent concurrent instances)?

If not, is there a way I can share access to an in-memory singleton within my application's Job implementation (is this through the JobExecutionContext?) so I can handle the concurrency myself? (and detect if a previous instance is running)


update: After floundering around in the docs, here's a couple of approaches I am considering, but either don't know how to get them to work, or there are problems.

  1. Use StatefulJob. This prevents concurrent access... but I'm not sure what other side-effects would occur if I use it, also I want to avoid the following situation:

    Suppose trigger times would be every minute, i.e. trigger#0 = at time 0, trigger #1 = 60000msec, #2 = 120000, #3 = 180000, etc. and the trigger#0 at time 0 fires my job which takes 130000msec. With a plain Job, this would execute triggers #1 and #2 while job trigger #0 is still running. With a StatefulJob, this would execute triggers #1 and #2 in order, immediately after #0 finishes at 130000. I don't want that, I want #1 and #2 not to run and the next trigger that runs a job should take place at #3 (180000msec). So I still have to do something else with StatefulJob to get it to work the way I want, so I don't see much of an advantage to using it.

  2. Use a TriggerListener to return true from vetoJobExecution().

    Although implementing the interface seems straightforward, I have to figure out how to setup one instance of a TriggerListener declaratively. Can't find the docs for the xml file.

  3. Use a static shared thread-safe object (e.g. a semaphore or whatever) owned by my class that implements Job.

    I don't like the idea of using singletons via the static keyword under Tomcat/Quartz, not sure if there are side effects. Also I really don't want them to be true singletons, just something that is associated with a particular job definition.

  4. Implement my own Trigger which extends SimpleTrigger and contains shared state that could run its own TriggerListener.

    Again, I don't know how to setup the XML file to use this trigger rather than the standard <trigger><simple>...</simple></trigger>.

解决方案

when your Quartz job wakes up you can do:

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
    }

这篇关于quartz:防止jobs.xml中的作业的并发实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆