我有一个具有以下定义的批处理作业:

<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中声明的范围内实例化,并且在其包含的范围内有效。与工件生命周期有关的范围有两个:jobstep

在您的案例中,您可以使用@Scope("step")注释CustomItemWriter,并且由于您正在运行多线程批处理,因此每个线程都将创建自己的myCustomItemWriter实例,该实例仅在当前执行步骤中存在。

07-24 09:45
查看更多