这应该真的很容易。我使用的是在Apache Tomcat 6.0.18下运行的Quartz,我有一个jobs.xml文件,该文件设置了每分钟运行的计划作业。
我想做的是,如果下一个触发时间到来时该作业仍在运行,则我不想启动新作业,因此可以让旧实例完成。
有没有办法在Jobs.xml中指定此设置(防止并发实例)?
如果不是,是否可以共享我的应用程序Job实现中对内存中单例的访问(这是通过JobExecutionContext吗?),以便我自己处理并发性?(并检测以前的实例是否正在运行)
更新: 在文档中苦苦挣扎之后,我正在考虑以下两种方法,但是要么不知道如何使它们工作,要么有问题。
假设触发时间是每分钟,即触发#0 =在时间0,触发#1 = 60000msec,触发#2 = 120000,#3 = 180000,依此类推,触发在时间0的触发#0触发了我的工作,耗时130000msec。对于普通作业,它将在作业触发器#0仍在运行时执行触发器#1和#2。使用StatefulJob,它将在#0在130000之后完成后立即执行触发器#1和#2。我不希望那样,我不希望#1和#2运行,而下一个运行作业的触发器应该发生在#3(180000msec)。因此,我仍然必须对StatefulJob进行其他操作才能使其按我想要的方式工作,因此使用它并没有太大优势。
尽管实现接口似乎很简单,但我必须弄清楚如何以声明方式设置一个TriggerListener实例。 3. 使用static实现Job的类拥有的共享线程安全对象(例如,信号量或其他)。
static
我不喜欢通过staticTomcat / Quartz下的关键字使用单例的想法,不确定是否有副作用。另外,我真的不希望它们成为真正的单例,而只是与特定工作定义相关联的东西。
同样,我不知道如何设置XML文件以使用此触发器而不是使用standard <trigger><simple>...</simple></trigger>。
<trigger><simple>...</simple></trigger>
当您的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 }