SpringBatch批处理框架默认使用单线程完成任务的执行,但是他提供了对线程池的支持。使用tasklet的task-executor属性可以很容易的将普通的step转成多线程的step。
task-executor:任务执行处理器,定义后采用多线程执行任务,需要考虑线程安全问题。 throttle-limit:最大使用线程池数目。
如果我们希望示例中的 billingStep 以并发方式执行,且并发任务数为 5,那么只需要做如下配置即可,见清单:
<step id="billingStep" next="payStep">
<tasklet task-executor="taskExecutor" throttle-limit="5">
<chunk reader="userDbReader" processor="billingProcessor"
writer="billDbWriter" commit-interval="5" chunk-completion-policy="">
</chunk>
</tasklet>
</step>
<beans:bean id="taskExecutor"
class="org.springframework.core.task.SimpleAsyncTaskExecutor">
</beans:bean>
Spring Core 为我们提供了多种执行器实现(包括多种异步执行器),我们可以根据实际情况灵活选择使用。
类名 | 描述 | 是否异步 |
---|---|---|
SyncTaskExecutor | 简单同步执行器 | 否 |
ThrottledTaskExecutor | 该执行器为其他任意执行器的装饰类,并完成提供执行次数限制的功能 | 视被装饰的执行器而定 |
SimpleAsyncTaskExecutor | 简单异步执行器,提供了一种最基本的异步执行实现 | 是 |
WorkManagerTaskExecutor | 该类作为通过 JCA 规范进行任务执行的实现,其包含 JBossWorkManagerTaskExecutor 和 GlassFishWorkManagerTaskExecutor 两个子类 | 是 |
ThreadPoolTaskExecutor | 线程池任务执行器 | 是 |
在多线程step中为了保证代码处理的正确性,要求所有在多线程step中处理的对象和操作必须都是线程安全的。但是SpringBatch框架提供的大部分的ItemReader、ItemWriter都不是线程安全的。所以需要自己保证多线程处理时候的线程安全。
那么,如何保证step的线程安全呢?
1.对reader的read方法使用synchronized关键字。
这种方式并不支持重启操作。当执行失败的时候并没有保存当前的状态数据导致无法知道哪些数据已经读取,哪些数据未读取。
多线程step提供了多个线程执行一个step的能力,但这种场景在实际业务中是用的并不是非常多。更多的是job中不同的step没有先后顺序,可以在执行期间并行的执行。SpringBatch提供了并行step的能力。可以通过split
元素来定义并行的作业流。