使用lambda函数的Java并行化

时间:2018-03-16 13:00:56

标签: java lambda parallel-processing

我有一些带有方法process()的对象数组,我想要并行化运行。我想尝试lambdas来实现并行化。所以我尝试了这个:

Arrays.asList(myArrayOfItems).forEach(item->{
    System.out.println("processing " + item.getId());
    item.process();
});

每个process()调用大约需要2秒钟。而且我注意到“并行化”方法仍然没有加速。似乎所有东西仍在运行序列化。 ID是按顺序打印的(有序),每次打印之间都会有2秒的暂停。

可能我误解了一些事情。使用lambdas并行执行此操作需要什么(希望以非常简洁的方式)?

3 个答案:

答案 0 :(得分:2)

Lambdas本身并没有并行执行任何操作。 Stream能够做到这一点。

查看方法Collection#parallelStreamdocumentation):

Arrays.asList(myArrayOfItems).parallelStream().forEach(...);

但请注意,实际并行时无法保证或控制。从其文档:

  

以此集合作为源,返回可能并行的流。此方法允许 返回顺序流

原因很简单。你真的需要很多你的集合中的元素(如数百万)进行并行化以实际获得回报(或做其他重要的事情)。并行化引入的开销是巨大。因此,如果它认为它会更快,那么该方法可能会选择使用顺序流。

在考虑使用并行性之前,您应该设置一些基准来测试它是否能够改进。有许多例子,人们只是盲目地使用它而没有注意到它们实际上降低了性能。另请参阅Should I always use a parallel stream when possible?

您可以使用Streamdocumentation)检查Stream#isParallel是否并列。

如果直接在流上使用Stream#paralleldocumentation),则会获得并行版本。

答案 1 :(得分:1)

方法Collection.forEach()只是迭代所有元素。它被称为内部迭代,因为它留给了它将迭代的集合如何,但它仍然是对所有元素的迭代。

如果要进行并行处理,则必须:

  1. 从集合中获取并行流。
  2. 指定将在流上完成的操作。
  3. 如果需要,请对结果执行某些操作。
  4. 您可以在此处阅读我的解释的第一部分:https://stackoverflow.com/a/22942829/2886891

答案 2 :(得分:1)

要创建并行流,请在集合

上调用操作.parallelStream

请参阅https://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html

Arrays.asList(myArrayOfItems).parallelStream().forEach(item->{
    System.out.println("processing " + item.getId());
    item.process();
});