quartz:防止jobs.xml中的作业的并发实例 [英] quartz: preventing concurrent instances of a job in jobs.xml
问题描述
这应该很容易。我使用Quartz在Apache Tomcat 6.0.18下运行,我有一个工作
我想做的是,如果作业仍在运行,当下一个触发时间滚动,我不想开始一个新的工作,所以我可以让老实例完成。
是否有办法在工作中指定。如果没有,是否有一种方式,我可以共享访问内存中的单例在我的应用程序的
< /www.quartz-scheduler.org/docs/api/org/quartz/Job.htmlrel =nofollow noreferrer> Job 实现(就是通过 JobExecutionContext ?)所以我可以自己处理并发? (并检测上一个实例是否正在运行)
更新: docs,这里有一些我正在考虑的方法,但是不知道如何让他们工作,或有问题。
-
使用 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做其他事情,让它以我想要的方式工作,所以我没有看到使用它的优势。
- p>使用 TriggerListener 从vetoJobExecution返回true ()。
虽然实现接口看起来很简单,但我必须找出如何以声明方式设置一个TriggerListener实例。 找不到xml文件的文档。
-
使用我的实现Job的类拥有的
static
共享线程安全对象(例如信号量或其他)。
我不喜欢通过Tomcat / Quartz下的
static
关键字使用单例的想法,不知道是否有side效果。 -
实现我自己的触发,它扩展了 SimpleTrigger ,并且包含可以运行其自己的TriggerListener的共享状态。
同样,我不知道如何设置XML文件来使用此触发器,而不是标准
< trigger>< simple> ...< / simple> / trigger>
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.
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.
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.
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.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屋!