我有一个具有以下定义的批处理作业:
<batch:job id="job">
<batch:split id="main" task-executor="simpleAsyncTaskExecutor">
<batch:flow>
<batch:step id="getAccountDetails">
<batch:tasklet ref="getAccountDetailsTasklet"/>
</batch:step>
</batch:flow>
<batch:flow>
<batch:step id="processAccounts">
<batch:tasklet transaction-manager="transactionManager" task-executor="threadPoolTaskExecutor" throttle-limit="${processor.maxThreads}">
<batch:chunk reader="queueReader" writer="myCustomItemWriter" commit-interval="${processor.commitInterval}"/>
</batch:tasklet>
</batch:step>
</batch:flow>
</batch:split>
</batch:job>
myCustomItemWriter基本上遍历了queueReader传递的帐户列表,并将它们提交到数据库。
该作业可扩展为并行运行该块的100个线程。在myCustomItemWriter的类中,我有一个私有属性,该属性维护它处理的每个帐户的特定BigDecimal属性的总和。因此,如果有10000个帐户,我将有100个线程,每个线程处理100个帐户。我想捕获所有这10000个帐户的此属性的总和。
这是我的问题:ItemWriter是否为单例(因此,只需一个私有属性即可维持此总和)?如果不是,是否应该将计数器定义为AtomicReference bean并将其注入到我的编写器中,以便在所有100个线程中注入相同的属性实例?
最佳答案
如果使用@Component
注释编写者,则默认范围为单例。
但是,所有批处理工件在使用之前都会在作业XML中声明的范围内实例化,并且在其包含的范围内有效。与工件生命周期有关的范围有两个:job
和step
。
在您的案例中,您可以使用@Scope("step")
注释CustomItemWriter,并且由于您正在运行多线程批处理,因此每个线程都将创建自己的myCustomItemWriter
实例,该实例仅在当前执行步骤中存在。