猿问

lambda foreach parallelStream 创建的数据少于预期

我正在尝试实现一个数组列表的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


  }

);

到目前为止我尝试过的事情


将结果收集到一个新的列表中...


collect(Collectors.toList())

...然后遍历新列表并执行第一个代码片段中描述的逻辑。新的 'collected' 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 插入中完成。


Cats萌萌
浏览 275回答 1
1回答

HUH函数

lambda 中的代码很可能不是线程安全的,因为代码使用共享的非并发数据结构,或者它们的操作需要锁定我怀疑批量/批量插入会比并行版本更快,并行版本可能会以庞大的短期连接结束,这些连接会在它们之间竞争锁定您正在插入的表。也许您可以在并行编写批量插入文件内容方面有所收获,但这取决于如何通过您的数据库 API 实现批量插入......是否需要先转储到文本文件中?在这种情况下,您的并行流可以并行组成该文本的不同行,最后将它们加入文本文件以加载到数据库中。也许它允许您在内存中使用语句对象的集合/列表而不是文本文件,在这种情况下,您并行流可以并行创建这些对象并将它们收集到最终的集合/列表中以批量插入到您的数据库中.
随时随地看视频慕课网APP

相关分类

Java
我要回答