Spring批量仅限制单个作业实例

我有一个春季批处理作业,可以通过restURL踢。 我想确保只允许一个作业实例运行。 如果另一个实例已经运行,那么不要启动另一个 即使参数不同。

我搜查了一下,没有找到任何解决方案。 考虑扩展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定义:

      

我通过创建JobExecutionListner解决了这个问题,并在JobExplorer的帮助下检查了是否正在运行任何其他实例,然后停止当前作业。我创建了监听器,以便它可以插入到需要这种场景的任何作业中。

 Set 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())  

或者,作为对REST URL的响应,如果您的作业使用作业的细节业务规则运行,请使用JobExplorer进行检查

我认为像下面这样的简单方法可能会起到作用:

 @Autowire private JobExplorer jobExplorer; private boolean isJobRunning(Job job) { Set jobExecutions = jobExplorer.findRunningJobExecutions(job.getName()); return !jobExecutions.isEmpty(); } 

然后,在执行作业之前进行检查:

 private void executeJob(Job job, @Nonnull JobParameters params) { if (isJobRunning(job)) { return; } try { jobLauncher.run(job, params); } catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException | JobParametersInvalidException e) { log.error("could not run job " + jobIdentifier, e); } }