Java Spring Batch FlowJobBuilder:并行和顺序执行;“工作步骤”;类型步骤

Java Spring Batch FlowJobBuilder:并行和顺序执行;“工作步骤”;类型步骤,java,multithreading,spring-batch,job-scheduling,Java,Multithreading,Spring Batch,Job Scheduling,我有一份由不同的工作步骤组成的工作。 我想同时触发一批这些作业步骤(作业步骤1 |作业步骤2 |作业步骤3)(在不同线程中与AsyncTaskExecutor一起运行) 以及其他作业步骤完成时的最后一个作业步骤(作业步骤4)。 因此,我为每个作业步骤创建了不同的流,并使用AsyncTaskExecutor将它们放在一个流中。 我还为最后一个作业步骤创建了一个流程 作业步骤1 |作业步骤2 |作业步骤3完成时 作业步骤4 下面的代码表示我的实现: Flow flowJob1= new FlowB

我有一份由不同的工作步骤组成的工作。 我想同时触发一批这些作业步骤(作业步骤1 |作业步骤2 |作业步骤3)(在不同线程中与AsyncTaskExecutor一起运行) 以及其他作业步骤完成时的最后一个作业步骤(作业步骤4)。 因此,我为每个作业步骤创建了不同的流,并使用AsyncTaskExecutor将它们放在一个流中。 我还为最后一个作业步骤创建了一个流程

作业步骤1 |作业步骤2 |作业步骤3完成时 作业步骤4

下面的代码表示我的实现:

 Flow flowJob1= new FlowBuilder<Flow>(jobStep.getName()).from((JobStep)jobStep1).end(); 

 Flow flowJob2= new FlowBuilder<Flow>(jobStep.getName()).from((JobStep)jobStep2).end(); 

Flow flowJob3= new FlowBuilder<Flow>(jobStep.getName()).from((JobStep)jobStep3).end(); 

Flow flowJob4= new FlowBuilder<Flow>(jobStep.getName()).from((JobStep)jobStep4).end(); 

 Flow splitFlow = new FlowBuilder<Flow>("splitflow").split(new SimpleAsyncTaskExecutor()).add(flowJob1,flowJob2,flowJob3).build(); 
问题是:
主作业不会等待所有作业步骤(在不同线程中)完成,然后运行下一个作业步骤。是否有我应该执行的任何spring批处理配置来解决此问题?

您需要将
JobStep
1-3组合成一个
FlowStep
。然后使用常规的
SimpleJobBuilder
构建作业

Flow flowJob1= new FlowBuilder<Flow>(jobStep.getName()).from((JobStep)jobStep1).end(); 

Flow flowJob2= new FlowBuilder<Flow>(jobStep.getName()).from((JobStep)jobStep2).end(); 

Flow flowJob3= new FlowBuilder<Flow>(jobStep.getName()).from((JobStep)jobStep3).end(); 

// Don't need this
// Flow flowJob4= new FlowBuilder<Flow>(jobStep.getName()).from((JobStep)jobStep4).end(); 

Flow splitFlow = new FlowBuilder<Flow>("splitflow").split(new SimpleAsyncTaskExecutor()).add(flowJob1,flowJob2,flowJob3).build();

FlowStep flowStep = new FlowStep(splitFlow);

SimpleJobBuilder jobBuilder = new JobBuilder(yourJobName).start(flowStep);

jobBuilder.next(jobStep4);
Flow flowJob1=新的FlowBuilder(jobStep.getName()).from((jobStep)jobStep1.end();
Flow flowJob2=新的FlowBuilder(jobStep.getName()).from((jobStep)jobStep2.end();
Flow flowJob3=新的FlowBuilder(jobStep.getName()).from((jobStep)jobStep3.end();
//我不需要这个
//Flow flowJob4=新的FlowBuilder(jobStep.getName()).from((jobStep)jobStep4.end();
Flow splitFlow=新的FlowBuilder(“splitFlow”).split(新的SimpleAsyncTaskExecutor()).add(flowJob1、flowJob2、flowJob3.build();
FlowStep FlowStep=新的FlowStep(分流);
SimpleJobBuilder jobBuilder=新的jobBuilder(您的JobName).start(flowStep);
jobBuilder.next(作业步骤4);

能否提供有关如何创建作业步骤的更多信息

TL;医生:

@Bean
public Step jobStepJobStep1(JobLauncher jobLauncher) {
        return this.stepBuilderFactory.get("jobStepJobStep1")
                                .job(job())
                                .launcher(jobLauncher)
                                .parametersExtractor(jobParametersExtractor())
                                .build();
}
尝试从jobStep定义中删除启动器。它对我有用。 我想这可能是《邮报》的问题

背景

我的工作流程是:
1.并行运行作业1、作业2和作业3。我通过split()提供executor。所有这些作业实际上都是作业步骤
2.无论1)的结果如何,执行EndJob

    @Bean
    public Job dataSync(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        Step pricingJobStep = new JobStepBuilder(new StepBuilder("pricingJobStep"))
                .job(pricingJob())
                .launcher(jobLauncher)
                .repository(jobRepository)
                .transactionManager(transactionManager)
                .build();
        Flow pricingFlow = new FlowBuilder<Flow>("pricing-flow").start(
                pricingJobStep
        ).build();

        Step referenceJobStep = new JobStepBuilder(new StepBuilder("referenceJobStep"))
                .job(referenceJob())
                .launcher(jobLauncher)
                .repository(jobRepository)
                .transactionManager(transactionManager)
                .build();

        Flow referenceFlow = new FlowBuilder<Flow>("reference-flow").start(
                referenceJobStep
        ).build();
        Step tradeJobStep = new JobStepBuilder(new StepBuilder("tradeJobStep"))
                .job(tradeJob())
                .launcher(jobLauncher)
                .repository(jobRepository)
                .transactionManager(transactionManager)
                .build();
        Flow tradeFlow = new FlowBuilder<Flow>("trade-flow").start(
                tradeJobStep
        ).build();
        SimpleAsyncTaskExecutor simpleAsyncTaskExecutor = new SimpleAsyncTaskExecutor("ETL-EXEC");


        Flow etlFlow = new FlowBuilder<Flow>("etl-flow")
                .split(simpleAsyncTaskExecutor)
                .add(pricingFlow,referenceFlow,tradeFlow)
                .build();


        return jobBuilderFactory.get("data-sync")
                .start(etlFlow)
                .on("COMPLETED")
                .to(finalStep())
                .from(etlFlow)
                .on("FAILED")
                .to(finalStep())
                .end().build();
    }

我的猜测是,这可能是我无法完成可以等待所有作业步骤的结束任务的原因。这仅仅是因为它们在不同的执行器中启动,对流没有任何控制。

非常感谢您的响应,但即使这样,父作业(线程)似乎也不会等待拆分流中的子作业(线程)完成其作业。它异步运行。而且它会在完成另一个任务之前触发jobStep4,这当然很烦人。但这里有你能做的,真正迫使它的手。。。向所有4个作业添加一个
JobExecutionLister
,并声明一个它们共享引用的单例
新倒计时锁存器(3)
。在作业1-3中,将它们置于
afterJob()
方法中。在作业4中,在
beforeJob()
方法中使用
wait()
。这将阻止工作4做任何工作,直到其他人都完成。是的,这就是我现在想做的。我会将Step executionListener放在每个JobStep上。非常感谢您的支持如果您可以在JUnit中复制它,您可能希望将其放在github上,并打开一张针对Spring batch的票据
    @Bean
    public Job dataSync(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        Step pricingJobStep = new JobStepBuilder(new StepBuilder("pricingJobStep"))
                .job(pricingJob())
                .launcher(jobLauncher)
                .repository(jobRepository)
                .transactionManager(transactionManager)
                .build();
        Flow pricingFlow = new FlowBuilder<Flow>("pricing-flow").start(
                pricingJobStep
        ).build();

        Step referenceJobStep = new JobStepBuilder(new StepBuilder("referenceJobStep"))
                .job(referenceJob())
                .launcher(jobLauncher)
                .repository(jobRepository)
                .transactionManager(transactionManager)
                .build();

        Flow referenceFlow = new FlowBuilder<Flow>("reference-flow").start(
                referenceJobStep
        ).build();
        Step tradeJobStep = new JobStepBuilder(new StepBuilder("tradeJobStep"))
                .job(tradeJob())
                .launcher(jobLauncher)
                .repository(jobRepository)
                .transactionManager(transactionManager)
                .build();
        Flow tradeFlow = new FlowBuilder<Flow>("trade-flow").start(
                tradeJobStep
        ).build();
        SimpleAsyncTaskExecutor simpleAsyncTaskExecutor = new SimpleAsyncTaskExecutor("ETL-EXEC");


        Flow etlFlow = new FlowBuilder<Flow>("etl-flow")
                .split(simpleAsyncTaskExecutor)
                .add(pricingFlow,referenceFlow,tradeFlow)
                .build();


        return jobBuilderFactory.get("data-sync")
                .start(etlFlow)
                .on("COMPLETED")
                .to(finalStep())
                .from(etlFlow)
                .on("FAILED")
                .to(finalStep())
                .end().build();
    }
2019-10-24 00:34:06.218  INFO 28776 --- [      ETL-EXEC2] o.s.batch.core.job.SimpleStepHandler     : Executing step: [referenceJobStep]
2019-10-24 00:34:06.359  INFO 28776 --- [cTaskExecutor-2] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=reference-job]] launched with the following parameters: [{name=0}]
2019-10-24 00:34:06.449  INFO 28776 --- [cTaskExecutor-2] o.s.batch.core.job.SimpleStepHandler     : Executing step: [reference-etl]