并行化减少操作

时间:2017-11-13 05:26:22

标签: java java-stream

通过简单地将流更改为并行流,可以将通常的“max”操作分配为多个核心上的reduce操作吗?
如何在不同线程的结果之间进行最终协调(没有明确的组合器)?

List<Employee> emps = new ArrayList<>();
emps.add(new Employee("Roy1",32));
emps.add(new Employee("Roy2",12));
emps.add(new Employee("Roy3",22));
emps.add(new Employee("Roy4",42));
emps.add(new Employee("Roy5",52));

Integer maxSal= emps.parallelStream().mapToInt(e -> e.getSalary()).reduce((a,b)->Math.max(a, b)).getAsInt();

System.out.println("Maximum in parallel " + maxSal);

2 个答案:

答案 0 :(得分:1)

是的,reduce可以并行化。但是,这需要您传递关联运算符。摘录自java.util.stream JavaDoc:

  

结合性

     

如果符合以下条件,则运算符或函数op是关联的:

     

(a op b)op c == a op(b op c)

     

如果我们将其扩展到四个术语,可以看出这对并行评估的重要性:

     

a op b op c op d ==(a op b)op(c op d)

     

因此我们可以与(c op d)并行地评估(a op b),然后在结果上调用op。   关联操作的示例包括数字加法,最小值和最大值以及字符串连接。

答案 1 :(得分:1)

如果操作(包括内部操作)具有良好的属性,则并行化流没有问题。 API说(减少):

  

[...]正确构造的reduce操作本质上是可并行化的,   只要用于处理元素的函数是   联想和无国籍。 [...]

关联和无状态的定义(在文档中):

  

无状态操作(例如过滤器和地图)不会保留任何状态   处理新元素时先前看到的元素 - 每个元素   可以独立于其他元素的操作进行处理。

  

如果符合以下条件,则运算符或函数op 关联

 (a op b) op c == a op (b op c)  
     

如果我们将其扩展到四个术语,可以看出这对并行评估的重要性:

 a op b op c op d == (a op b) op (c op d)  
     

因此我们可以与(c op d)并行地评估(a op b),然后在结果上调用op。

粗略地说,如果操作是关联的和无状态的,则意味着您可以按任何顺序应用它以获得结果。因此,可以应用任何良好的通用收集。请记住,Java 8流基于Fork-Join池,因此聚集是众所周知的。关于该主题的教程显示了基础知识:

if (my portion of the work is small enough)
  do the work directly
else
  split my work into two pieces
  invoke the two pieces and wait for the results
相关问题