通过简单地将流更改为并行流,可以将通常的“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);
答案 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