也许这是一个反复出现的问题,但我需要根据我的背景进行一些自定义。
我使用的是Spring Batch 3.0.1.RELEASE
我有一些简单的工作,有一些步骤。一步是像这样的块:
<tasklet transaction-manager="myTransactionManager">
<batch:chunk reader="myReader" processor="myProcessor" writer="myWriter" commit-interval="${commit.interval}">
</batch:chunk>
<bean id="myProcessor" class="org.springframework.batch.item.support.CompositeItemProcessor" scope="step">
<property name="delegates">
<list>
<bean class="...MyFirstProcessor">
</bean>
<bean class="...MySecondProcessor">
</bean>
</list>
</property>
通过这种配置,我的工作完美无缺。
现在,我想将其转换为多线程作业。 在documentation to basic multi-thread jobs之后,我在tasklet中包含了一个SympleAsyncTaskExecutor,但它失败了。
我已经知道JdbcCursorItemReader在多线程执行时无法正常工作(是不是?)。我已经将读者更改为JdbcPagingItemReader,这是一场噩梦:作业不会失败,编写过程没问题,但数据在线程中混合,客户数据不正确且连贯(客户已经<来自其他人的服务,地址等。
。那么,为什么会这样呢?我怎样才能更改为多线程作业?
我非常关心和困惑,所以任何帮助都会非常感激。 非常感谢。
[编辑已解决]
嗯,我的问题的正确和合适的解决方法是从开始设计多线程和线程安全执行的作业。习惯性地首先使用单线程步骤执行来理解和了解Spring Batch概念;但如果你认为你要离开这个阶段,必须提出诸如不可变对象,线程安全列表,地图等的考虑因素。
当前我的问题状态中的当前修复是我后面描述的下一个。在测试了马丁的建议并考虑到迈克尔的指导方针后,我终于解决了我的问题。接下来的步骤不是很好的做法,但我无法从开始重建我的工作:
因此,如果委托的bean是:
<bean class="...MyProcessor">
<property name="otherBean" ref="otherBeanID" />
更改为:
<bean class="...MyProcessor">
<property name="otherBean" value="otherBeanID" />
并且,在MyProcessor中,从上下文获取 otherBeanID 的单个实例; otherBeanID 必须使用scope =&#34; protoype&#34;进行配置。
正如我之前所说,他们并没有好的风格,但这是我最好的选择,我可以断言每个线程都有自己的不同的项目实例和其他bean实例。
它证明某些类没有很好地设计用于正确的多线程执行。
马丁,迈克尔,感谢您的支持。
我希望对任何人都有帮助。
答案 0 :(得分:6)
您在问题中提出了很多问题(将来,请将此类问题分解为多个更具体的问题)。但是,逐项:
JdbcCursorItemReader
线程安全吗?
作为documentation states,它不是。原因是JdbcCursorItemReader
包装了一个非线程安全的ResultSet
。
复合处理器和编写器是否适用于多线程?
只要委托CompositeItemProcessor
实现也是线程安全的,Spring Batch提供的ItemProcessor
被认为是线程安全的。您不提供与您的实现或其配置相关的代码,因此我无法验证其线程安全性。但是,鉴于您所描述的症状,我的预感是您的代码中存在某种形式的线程安全问题。
您也没有确定正在使用的ItemWriter
实现或其配置,因此也可能存在与线程相关的问题。
如果您使用有关实施和配置的更多信息更新问题,我们可以提供更多信息。
我如何制作自定义线程安全的复合处理器?
实施任何ItemProcessor
时需要考虑两件事:
ItemProcessor
实现具有幂等性,可以防止多次通过处理器的副作用。 也许它可能是JDBC阅读器:多线程是否有任何线程安全的JDBC阅读器?
如您所知,JdbcPaginingItemReader
是线程安全的,并在documentation中注明。当使用多个线程时,每个块都在它自己的线程中执行。如果您已将页面大小配置为与提交间隔匹配,则表示每个页面都在同一个线程中处理。
缩放单个步骤的其他选项
当您走上实现单线程,多线程步骤的道路时,可能会有更好的选择。 Spring Batch提供了5个核心扩展选项:
ItemProcessor
和复合ItemWriter
,这可能需要探索(将当前复合方案分解为多个并行步骤)。ItemProcessor
/ ItemWriters
- 此选项允许您在不同的线程中执行处理器逻辑。处理器将线程关闭并将Future
返回到AsyncItemWriter
,Future
将阻塞,直到ItemProcessor
返回写入。您可以在这里阅读Spring Batch文档中的所有这些选项:http://docs.spring.io/spring-batch/trunk/reference/html/scalability.html
线程安全是一个复杂的问题。只需将多个线程添加到曾经在单线程环境中工作的代码,通常就会发现代码中的问题。