Java quartz:在jobs.xml中防止作业的并发实例
这应该很容易。我正在使用ApacheTomcat6.0.18下运行的Quartz,我有一个可以设置每分钟运行的计划作业的程序 我想做的是,如果在下一个触发时间到来时作业仍在运行,我不想启动新作业,所以我可以让旧实例完成 有没有办法在jobs.xml(防止并发实例)中指定这一点 如果没有,是否有一种方法可以在我的应用程序实现中共享对内存中单例的访问(是否通过?),以便我自己处理并发?(并检测上一个实例是否正在运行)Java quartz:在jobs.xml中防止作业的并发实例,java,concurrency,quartz-scheduler,Java,Concurrency,Quartz Scheduler,这应该很容易。我正在使用ApacheTomcat6.0.18下运行的Quartz,我有一个可以设置每分钟运行的计划作业的程序 我想做的是,如果在下一个触发时间到来时作业仍在运行,我不想启动新作业,所以我可以让旧实例完成 有没有办法在jobs.xml(防止并发实例)中指定这一点 如果没有,是否有一种方法可以在我的应用程序实现中共享对内存中单例的访问(是否通过?),以便我自己处理并发?(并检测上一个实例是否正在运行) 更新:在文档中苦苦挣扎之后,我正在考虑几种方法,但要么不知道如何让它们发挥作用,
更新:在文档中苦苦挣扎之后,我正在考虑几种方法,但要么不知道如何让它们发挥作用,要么存在问题
静态
共享线程安全对象(例如信号量或任何东西)
我不喜欢通过Tomcat/Quartz下的static
关键字使用单例的想法,不确定是否有副作用。另外,我真的不希望他们是真正的单身汉,只是与特定的工作定义相关的东西…
我完成了类似的工作,实现了我的作业类,确保在当前运行的作业完成之前没有其他作业启动 希望有帮助;)
我用JBoss实现了它。。。但我不认为这有什么区别。当你的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
}
JobDetail existingJobDetail=sched.getJobDetail(jobName,jobGroup);
如果(existingJobDetail!=null){
List currentlyExecutingJobs=(List)sched.getCurrentlyExecutingJobs();
for(JobExecutionContext jec:CurrentlyExecutionJobs){
if(existingJobDetail.equals(jec.getJobDetail())){
//字符串消息=jobName+“已在运行。”;
//日志信息(消息);
//抛出新JobExecutionException(消息,false);
}
}
//sched.deleteJob(jobName,jobGroup);如果要删除计划但当前未运行的作业
}
能否将作业设置为StatefulJob,并为您创建的每个触发器设置作业的Misfire指令,使其在丢失时不触发?不确定您使用的是哪种类型的作业,但您必须对适用于触发器类型的缺火说明进行一些研究
谢谢,
迪米特里斯利的答案不完整,所以这是我的 当Quartz作业唤醒时,它会将其JobExecutionContext返回给您。 我假设你想用相同的触发器跳过作业
List<JobExecutionContext> jobs = jobExecutionContext.getScheduler().getCurrentlyExecutingJobs();
for (JobExecutionContext job : jobs) {
if (job.getTrigger().equals(jobExecutionContext.getTrigger()) && !job.getJobInstance().equals(this)) {
logger.info("There's another instance running, so leaving" + this);
return;
}
}
List jobs=jobExecutionContext.getScheduler().getCurrentlyExecutionJobs();
for(JobExecutionContext作业:作业){
if(job.getTrigger().equals(jobExecutionContext.getTrigger())&&!job.getJobInstance().equals(this)){
info(“有另一个实例正在运行,所以留下“+this”);
返回;
}
}
我们获取当前作业上下文,并检查是否存在具有相同触发器的前一个作业实例。如果是这种情况,我们只需跳过返回。还有另一个更简单的解决方案。可以为作业指定一个DisallowConcurrentExecution注释,该注释可防止多个并发实例运行。见文件 链接一直断开,因此下面是相关示例
@DisallowConcurrentExecution
public class ColorJob implements Job {
scaramouche溶液的轻微变化
List<JobExecutionContext> jobs = jobExecutionContext.getScheduler().getCurrentlyExecutingJobs();
for (JobExecutionContext job : jobs) {
if (job.getTrigger().equals(jobExecutionContext.getTrigger()) && !job.getFireInstanceId().equals(jobExecutionContext.getFireInstanceId()) {
logger.info("There's another instance running, so leaving" + this);
return;
}
}
List jobs=jobExecutionContext.getScheduler().getCurrentlyExecutionJobs();
for(JobExecutionContext作业:作业){
if(job.getRigger().equals(jobExecutionContext.getRigger())&&!job.getFireInstanceId().equals(jobExecutionContext.getFireInstanceId()){
info(“有另一个实例正在运行,所以留下“+this”);
返回;
}
}
如果所有作业执行都使用单个实例(使用自定义JobFactory类返回单例,而不是每次执行调用newInstance()),scaramouche的解决方案就会失败。如果您使用的是
org.springframework.scheduling.quartz.QuartzJobBean
:
受保护的void executeInternal(JobExecutionContext上下文)引发JobExecutionException{
试一试{
调度器调度器=context.getScheduler();
List jobs=scheduler.getCurrentlyExecutingJobs();
for(JobExecutionContext作业:作业){
if(job.getTrigger().equals(context.getTrigger())&&job.getJobDetail()!=context.getJobDetail()){
LOG.warn(“忽略!”);
返回;
}
}
...
}捕获(调度){
LOG.error(“真幸运!:”(,e);
}