Spring boot 当两个作业尝试使用同一个表时,Spring批处理锁定资源
我使用的是Spring boot&Spring batch,如果表A(表A)中已经有作业,我想锁定表A中的访问权限,因此我想将作业放在等待列表中,直到上一个作业完成并重新启动已停止的作业 目前,我可以使用**JobExecutionListener**的**beforeJob**和**afterJob**方法停止同一实例的作业,并在另一个作业(具有同一实例)结束时重新启动它。但当两个不同的作业具有相同的参数(访问相同的表)时,我无法进行检查 这是我的密码:Spring boot 当两个作业尝试使用同一个表时,Spring批处理锁定资源,spring-boot,spring-batch,Spring Boot,Spring Batch,我使用的是Spring boot&Spring batch,如果表A(表A)中已经有作业,我想锁定表A中的访问权限,因此我想将作业放在等待列表中,直到上一个作业完成并重新启动已停止的作业 目前,我可以使用**JobExecutionListener**的**beforeJob**和**afterJob**方法停止同一实例的作业,并在另一个作业(具有同一实例)结束时重新启动它。但当两个不同的作业具有相同的参数(访问相同的表)时,我无法进行检查 这是我的密码: private void runJob
private void runJobB(Job parJob) throws Exception {
log.info("[Job] running ...........");
Map<String, JobParameter> confMap = new HashMap<>();
confMap.put("value", new JobParameter("label_test"));
confMap.put("time", new JobParameter(System.currentTimeMillis()));
JobParameters jobParameters = new JobParameters(confMap);
try {
jobLauncher.run(parJob, jobParameters);
} catch (Exception ex) {
log.error("job1 : " + ex.getMessage());
}
}
private void runJobB(作业parJob)引发异常{
log.info(“[作业]正在运行…………”);
Map confMap=newhashmap();
confMap.put(“值”,新作业参数(“标签测试”);
confMap.put(“time”,新作业参数(System.currentTimeMillis());
JobParameters JobParameters=新的JobParameters(confMap);
试一试{
jobLauncher.run(parJob,jobParameters);
}捕获(例外情况除外){
log.error(“job1:+ex.getMessage());
}
}
公共类拦截JobExecution实现JobExecutionListener{
静态私有映射jobInformationsMap=newHashMap();
@自动连线
私人JobExplorer;
@自动连线
私有作业库作业库;
@自动连线
私人职业经营者;
@鬼鬼祟祟
@凌驾
作业前公共无效(作业执行作业执行){
log.info(“拦截作业执行-作业前!”);
最后一个字符串locJobName=jobExecution.getJobInstance().getJobName();
最终列表jobExecutionList=新的ArrayList(jobExplorer.findRunningJobExecutions(locJobName));
if(jobExecutionList.size()>1){
for(JobExecution jobExecution1:jobExecutionList){
已同步(作业执行1){
jobInformationsMap.put(jobExecution1.getId(),jobExecution1);
jobExecution1.setEndTime(新日期());
jobExecution1.setStatus(BatchStatus.FAILED);
jobExecution1.setExitStatus(ExitStatus.FAILED);
jobExecution1.stop();
}
}
}
}
私有void restart(){
试一试{
final Map.Entry first=getFirst();
final JobExecution JobExecution=first.getValue();
已同步(作业执行){
if(jobExecution.getStatus().equals(BatchStatus.STOPPING)){
jobRepository.update(作业执行);
重新启动(jobExecution.getId());
}
}
}捕获(异常e1){
e1.printStackTrace();
}
}
@鬼鬼祟祟
@凌驾
公共无效后作业(作业执行作业执行){
已同步(作业执行){
log.info(“拦截作业执行-作业后!”);
如果(作业信息映射大小()>1){
重启();
}
}
}
私有静态映射。条目getFirst(){
Map.Entry locJobExecution=null;
Date minCreateTime=Calendar.getInstance().getTime();
对于(Map.Entry locMap:jobInformationsMap.entrySet()){
最终日期createTime=locMap.getValue().getCreateTime();
if(minCreateTime.after(createTime)){
minCreateTime=createTime;
locJobExecution=locMap;
}
}
jobInformationsMap.remove(locJobExecution.getKey());
返回执行;
}
}
我到处都搜索过,但如果您能帮助我,我找不到与我想要的完全匹配的内容,谢谢。您遇到的是作业编排设计问题,而不是实施问题。你为什么不一个接一个地开始工作呢
我想将作业放在等待列表中,直到上一个作业完成为止
:使用作业请求队列并按顺序启动它们。
public class InterceptingJobExecution implements JobExecutionListener {
static private Map<Long, JobExecution> jobInformationsMap = new HashMap<>();
@Autowired
private JobExplorer jobExplorer;
@Autowired
private JobRepository jobRepository;
@Autowired
private JobOperator jobOperator;
@SneakyThrows
@Override
public void beforeJob(JobExecution jobExecution) {
log.info("Intercepting Job Excution - Before Job!");
final String locJobName = jobExecution.getJobInstance().getJobName();
final List<JobExecution> jobExecutionList = new ArrayList<>(jobExplorer.findRunningJobExecutions(locJobName));
if (jobExecutionList.size() > 1) {
for (JobExecution jobExecution1 : jobExecutionList) {
synchronized (jobExecution1) {
jobInformationsMap.put(jobExecution1.getId(), jobExecution1);
jobExecution1.setEndTime(new Date());
jobExecution1.setStatus(BatchStatus.FAILED);
jobExecution1.setExitStatus(ExitStatus.FAILED);
jobExecution1.stop();
}
}
}
}
private void restart() {
try {
final Map.Entry<Long, JobExecution> first = getFirst();
final JobExecution jobExecution = first.getValue();
synchronized (jobExecution) {
if(jobExecution.getStatus().equals(BatchStatus.STOPPING)) {
jobRepository.update(jobExecution);
jobOperator.restart(jobExecution.getId());
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
@SneakyThrows
@Override
public void afterJob(JobExecution jobExecution) {
synchronized (jobExecution) {
log.info("Intercepting Job Excution - After Job!");
if(jobInformationsMap.size() > 1) {
restart();
}
}
}
private static Map.Entry<Long, JobExecution> getFirst() {
Map.Entry<Long, JobExecution> locJobExecution = null;
Date minCreateTime = Calendar.getInstance().getTime();
for( Map.Entry<Long, JobExecution> locMap : jobInformationsMap.entrySet()) {
final Date createTime = locMap.getValue().getCreateTime();
if(minCreateTime.after(createTime)) {
minCreateTime = createTime;
locJobExecution = locMap;
}
}
jobInformationsMap.remove(locJobExecution.getKey());
return locJobExecution;
}
}