old*_*ort 5 java parallel-processing lambda java-8
我正在尝试实现一个数组列表的 lambda foreach 并行流,以提高现有应用程序的性能。
到目前为止,没有并行 Stream的foreach 迭代创建了写入数据库的预期数据量。
但是当我切换到 parallelStream 时,它总是向数据库中写入更少的行。假设从预期的 10.000 行开始,将近 7000 行,但结果在这里有所不同。
知道我在这里缺少什么,数据竞争条件,还是必须使用锁和同步?
代码基本上是这样的:
// Create Persons from an arraylist of data
arrayList.parallelStream()
.filter(d -> d.personShouldBeCreated())
.forEach(d -> {
// Create a Person
// Fill it's properties
// Update object, what writes it into a DB
}
);
Run Code Online (Sandbox Code Playgroud)
到目前为止我尝试过的事情
将结果收集到一个新列表中...
collect(Collectors.toList())
Run Code Online (Sandbox Code Playgroud)
...然后迭代新列表并执行第一个代码片段中描述的逻辑。新“收集”的ArrayList的大小与预期结果匹配,但最后在数据库中创建的数据仍然较少。
更新/解决方案:
根据我在该代码中标记的关于非线程安全部分的答案(以及评论中的提示) ,我将其实现如下,最终给了我预期的数据量。性能有所提升,现在只需要执行之前的 1/3。
StringBuffer sb = new StringBuffer();
arrayList()
.parallelStream()
.filter(d-> d.toBeCreated())
.forEach(d ->
sb.append(
// Build an application specific XML for inserting or importing data
)
);
Run Code Online (Sandbox Code Playgroud)
特定于应用程序的部分是基于 XML 的数据导入 api,但我认为这可以在普通的 SQL JDBC 插入中完成。
很可能您的 lambda 中的代码不是线程安全的,因为代码使用共享的非并发数据结构或者它们的操作需要锁定
我怀疑批量插入会比并行版本更快,并行版本可能会导致庞大的短实时连接,这些连接会在它们之间竞争锁定您正在插入的表。
也许您可以在并行编写批量插入文件内容方面获得一些收益,但这取决于如何通过数据库 API 实现批量插入......是否需要先将其转储到文本文件中?在这种情况下,您的并行流可以并行组成该文本的不同行,最后将它们连接到文本文件中以加载到数据库中。也许它允许您使用内存中语句对象的集合/列表,而不是文本文件,在这种情况下,并行流可以并行创建这些对象并将它们收集到最终的集合/列表中,以便批量插入到数据库中。
| 归档时间: |
|
| 查看次数: |
1261 次 |
| 最近记录: |