弹簧批次仅限制作业的单个实例
2022-09-04 02:48:47
我有一个弹簧批处理作业,可以通过休息URL踢出。我想确保只允许运行一个作业实例。如果另一个实例已经在运行,则不要启动另一个实例。即使参数不同。
我搜索了一下,没有找到任何开箱即用的解决方案。考虑扩展SimpleJobLauncher。以检查作业的任何实例是否正在运行。
我有一个弹簧批处理作业,可以通过休息URL踢出。我想确保只允许运行一个作业实例。如果另一个实例已经在运行,则不要启动另一个实例。即使参数不同。
我搜索了一下,没有找到任何开箱即用的解决方案。考虑扩展SimpleJobLauncher。以检查作业的任何实例是否正在运行。
您可以尝试拦截作业执行,实现 JobExecutionListener 接口:
public class MyJobExecutionListener extends JobExecutionListener {
//active JobExecution, used as a lock.
private JobExecution _active;
public void beforeJob(JobExecution jobExecution) {
//create a lock
synchronized(jobExecution) {
if(_active!=null && _active.isRunning()) {
jobExecution.stop();
} else {
_active=jobExecution;
}
}
}
public void afterJob(JobExecution jobExecution) {
//release the lock
synchronized(jobExecution) {
if(jobExecution==_active) {
_active=null;
}
}
}
}
然后,注入到作业定义:
<job id="myJobConfig">
<listeners>
<listener ref="myListener"/>
</listeners>
</job>
我通过创建一个JobExecutionListner解决了这个问题,在JobExplorer的帮助下,我检查了是否有任何其他实例正在运行,如果正在运行,那么停止当前作业。我创建了侦听器,以便它可以插入到任何需要此类方案的工作中。
Set<JobExecution> jobExecutions = ((SimpleJobExplorer) jobExplorer.getObject()).findRunningJobExecutions(jobExecution.getJobInstance().getJobName());
if(jobExecutions.size()>1){
Long currentTime = (new Date()).getTime();
for(JobExecution execution : jobExecutions ){
if(execution.getJobInstance().getId().compareTo(jobExecution.getJobInstance().getId())!=0 && (currentTime - execution.getStartTime().getTime()) <lockOverideTime){
jobExecution.stop();
throw new IllegalStateException("Another instance of the job running job name : " +jobExecution.getJobInstance().getJobName() );
}
}
}