运行SpringBatch Step parralel和sequential

时间:2015-09-28 15:26:31

标签: java spring spring-batch batch-processing

在Spring-Batch作业中,我有两个业务操作,A和B,每个都有几个步骤(1,2,3)。 我希望并行运行A1和B1,当两者都结束时,我想以并行方式运行A2和B2:

start
    A1-B1 in parallel
wait for both ended
    A2-B2 in parrallel
wait for both ended
    A3-B3 in parrallel
...

我试了一下:

@Bean
public Job test() {
    SimpleFlow splitFlow = new FlowBuilder<SimpleFlow>("Sequential Flow")
                    .split(new SyncTaskExecutor())
                    .add(flow1(), flow2())      
                    .build();

    return jobs.get("test").start(splitFlow).end().build();
}

private Flow flow1() {
    return new FlowBuilder<SimpleFlow>("parralel 1").split(new SimpleAsyncTaskExecutor())
                    .add(new FlowBuilder<SimpleFlow>("A1").start(stepA1()).build(), 
                        new FlowBuilder<SimpleFlow>("B1").start(stepB1()).build())
                    .build();
}

private Flow flow2() {
    return new FlowBuilder<SimpleFlow>("parralel 2").split(new SimpleAsyncTaskExecutor())
                    .add(new FlowBuilder<SimpleFlow>("A2").start(stepA2()).build(), 
                        new FlowBuilder<SimpleFlow>("B2").start(stepB2()).build())
                    .build();
}

它正在发挥作用。

但它也很难看,几乎不可读。有没有更容易做到的?

(我可以从一个工作岗位转到另一个工作岗位,再到工作岗位并让他们互相等待,但该怎么做?)

修改: 我在xml config中找到了等价物:

<batch:job id="test">
    <batch:split id="step_1" next="step_2">
        <batch:flow> 
             <batch:step id="A1"/>
        </batch:flow>
        <batch:flow> 
             <batch:step id="B1" />
        </batch:flow>
    </batch:split>
    <batch:split id="step_2">
        <batch:flow> 
             <batch:step id="A2"/>
        </batch:flow>
        <batch:flow> 
             <batch:step id="B2" />
        </batch:flow>
    </batch:split>
</batch:job>

我的所有配置目前都在Java配置中,但是对于这些作业,xml配置更易于阅读和理解。

1 个答案:

答案 0 :(得分:0)

如果只是可读性,有两种选择:

a)以不同方式格式化代码

private Flow flow1() {
    return new FlowBuilder<SimpleFlow>("parralel 1")
            .split(new SimpleAsyncTaskExecutor())
            .add(
                    new FlowBuilder<SimpleFlow>("A1").start(stepA1()).build(),
                    new FlowBuilder<SimpleFlow>("B1").start(stepB1()).build()
            ).build();
}

private Flow flow2() {
    return new FlowBuilder<SimpleFlow>("parralel 2")
            .split(new SimpleAsyncTaskExecutor())
            .add(
                    new FlowBuilder<SimpleFlow>("A2").start(stepA2()).build(),
                    new FlowBuilder<SimpleFlow>("B2").start(stepB2()).build())
            .build();
}

b)提取方法和变量

private TaskExecutor executor() {
    return new SimpleAsyncTaskExecutor();
}

private Flow flow1() {
    Flow subFlow1 = new FlowBuilder<SimpleFlow>("A1").start(stepA1()).build();
    Flow subFlow2 = new FlowBuilder<SimpleFlow>("B1").start(stepB1()).build();
    return new FlowBuilder<SimpleFlow>("parralel 1")
            .split(executor())
            .add(subFlow1, subFlow2)
            .build();
}


private Flow flow2() {
    Flow subFlow1 = new FlowBuilder<SimpleFlow>("A2").start(stepA2()).build();
    Flow subFlow2 = new FlowBuilder<SimpleFlow>("B2").start(stepB2()).build();
    return new FlowBuilder<SimpleFlow>("parralel 2")
            .split(executor())
            .add(subFlow1, subFlow2)
            .build();
}

顺便说一句,我很确定你应该在两个流程中使用相同的TaskExecutor。您可以通过将executor()方法设为public并将其标记为@Bean来实现此目的。然后Spring将确保只创建一次底层对象(参见The IOC Container)。所以上面的executor()方法实际上应该是:

@Bean
public TaskExecutor executor() {
    return new SimpleAsyncTaskExecutor();
}