我试图实现的拉姆达的foreach平行的ArrayList的流以改善现有的应用程序的性能。
到目前为止的的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())
...然后遍历新列表并执行逻辑,如第一个代码段所述。 的大小的新的“收集”的的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
)
);
应用程序特定部分是基于XML数据导入API,但是我认为这可能以纯SQL JDBC插入来进行。
答案 0 :(得分:3)
您最有可能在lambda中执行的代码不是线程安全的,因为该代码使用共享的非并发数据结构,或者它们的操作需要锁定
我怀疑批处理/批量插入要比并行版本快,并行版本可能会以扩展的短期连接而告终,它们之间的竞争也将锁定您要插入的表。
虽然在并行编写大容量插入文件内容方面可能会有所收获,但这取决于如何通过数据库API实现大容量插入...是否需要将其转储到文本文件中第一?在这种情况下,您的并行流可以并行组成该文本的不同行,最后将它们连接到文本文件中以加载到数据库中。也许它不是文本文件,而是允许您使用内存中的语句对象的集合/列表,在这种情况下,您可以并行创建这些对象的并行流,并将它们收集到最终的集合/列表中,以批量插入数据库中