在Spring Batch中

时间:2018-10-01 09:29:35

标签: java spring task spring-batch pool

我有以下春季批处理xml文件,其中定义了一个我想并行运行4个不同任务的作业:

    <split id="fillNDDependencies" task-executor="asyncTaskExecutor"
        next="decisionExecuteNDDependencies">
        <flow>
            <step id="fillTABLE1">
                <tasklet ref="runTABLE1Tasklet" />
            </step>
        </flow>
        <flow>
            <step id="fillTABLE2">
                <tasklet ref="runTABLE2Tasklet" />
            </step>
        </flow>
        <flow>
            <step id="fillTABLE3">
                <tasklet ref="runTABLE3Tasklet" />
            </step>
        </flow>
        <flow>
            <step id="fillTABLE4">
                <tasklet ref="runTABLE4Tasklet" />
            </step>
        </flow>
    </split>

我使用ThreadPoolTask​​Executor控制使用的线程数。

<bean id="asyncTaskExecutor"
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="1"></property>
    <property name="maxPoolSize" value="1"></property>
    <property name="queueCapacity" value="0"></property>
    <property name="keepAliveSeconds" value="10"></property>
</bean>

这里是问题:理想情况下,我想并行运行四个任务,但是有时我的机器会变得更加“忙碌”,并且我想一次只执行其中两个任务,取决于我计算机中可用的线程数,但不更改当前的拆分条件。

我试图限制我的任务执行器中的corePoolSize和maxPoolSize,但执行作业时出现以下错误:

org.springframework.batch.core.JobExecutionException: Flow execution ended unexpectedly
    at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:140)
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:304)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.batch.core.job.flow.FlowExecutionException: TaskExecutor rejected task for flow=fillNDDependencies1.1
    at org.springframework.batch.core.job.flow.support.state.SplitState.handle(SplitState.java:103)
    at org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean$DelegateState.handle(SimpleFlowFactoryBean.java:207)
    at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:165)
    at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144)
    at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:134)
    ... 5 more

因此,除非PoolSize与拆分内的步骤数匹配,否则该作业将无法工作。

我如何能够限制一次执行的任务,而不必在每次拆分中创建步骤更少的新作业?

谢谢。


请注意,这不是该问题How to set up multi-threading in Spring Batch?的重复,因为我已经在使用split作为并行执行任务的方式。

1 个答案:

答案 0 :(得分:0)

ThreadPoolTaskExecutor有一个名为queueCapacity的参数,用于设置执行者在开始拒绝任务之前可以接受多少个任务。您需要根据需要设置此参数。

现在,关于工作线程的数量,我在您的示例中看到将corePoolSize 以及 maxPoolSize设置为1,因此最多会有一个池中的线程。例如,如果您希望两个线程并行工作,则可以将corePoolSize设置为1,将maxPoolSize设置为2。

这些设置可以在运行时通过JMX动态更改。在此处查看Javadoc:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html#setMaxPoolSize-int-

希望这会有所帮助。