为了提高现有应用程序的性能,我正在尝试实现数组列表的lambda并行流。
到目前为止,在没有并行流的情况下,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
}
);到目前为止我尝试过的事物,
在一个新的列表中收集结果。
collect(Collectors.toList())然后,...and迭代新列表并执行第一个代码片段中描述的逻辑。新的“收集”的ArrayList的大小与预期的结果相匹配,但最终数据库中创建的数据仍然较少。
Update/Solution:
基于我在代码中标记的关于非线程安全部件的答案(以及注释中的提示),我按照以下方式实现了它,最后给出了预期的数据量。性能已经提高,现在只需要以前的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
)
);应用程序特定的部分是一个基于XML的数据导入api,但我认为这可以在普通的SQL插入中完成。
发布于 2019-01-29 18:44:50
最有可能的情况是,lambda中的代码不是线程安全的,因为代码使用共享的非并发数据结构或它们的操作需要锁定。
我怀疑批/批量插入会比并行版本更快,而并行版本可能会以庞大的短时间连接结束,这些连接将在它们之间竞争锁定您正在插入的表。
也许您可以在并行地组合大容量插入文件内容方面获得一些好处,但这将取决于如何通过数据库API实现大容量插入。它需要先转储到文本文件中吗?在这种情况下,您的并行流可以并行地组成文本的不同行,并最终将它们连接到文本文件中,加载到DB中。也许它不是文本文件,而是允许您在内存中使用语句对象的集合/列表,在这种情况下,并行流可以并行地创建这些对象,并将它们收集到最终的集合/列表中,然后批量插入到DB中。
https://stackoverflow.com/questions/54418983
复制相似问题