Java8 stream()。map()。reduce()实际上是map reduce

时间:2017-06-28 07:03:20

标签: java java-8

我在某处使用stream()。map()。reduce()看到了这段代码。

这个map()函数真的可以并行工作吗?如果是,那么它可以为map()函数启动多少个最大线程数?

如果我对下面的特定用例使用parallelStream()而不仅仅是stream(),该怎么办?

任何人都可以给我一个很好的例子,说明不使用parallelStream()

的位置
  

下面的代码只是从tCode中提取tName并返回逗号分隔的String。

String ts = atList.stream().map(tcode -> {
    return CacheUtil.getTCache().getTInfo(tCode).getTName();
}).reduce((tName1, tName2) -> {
    return tName1 + ", " + tName2;
}).get();

2 个答案:

答案 0 :(得分:5)

stream().map().reduce() 并行,因此单个线程会对流进行操作。

您必须添加parallel或其他情况parallelStream(取决于API,但它是相同的)。默认使用并行 ,您将获得可用处理器的数量 - 1;但主线程也在ForkJoinPool#commonPool中使用;因此通常会有2个,4个,8个线程等。要查看您将获得的数量,请使用:

Runtime.getRuntime().availableProcessors()

您可以使用自定义池并根据需要获取尽可能多的线程,如here所示。

另请注意,整个管道是并行运行的,而不是只是 map操作。

关于何时使用以及何时不使用并行流,没有一条黄金法则,最好的方法是衡量。但是有明显的选择,比如10个元素的流 - 这是方式太少,无法从并行化中获得任何实际好处。

答案 1 :(得分:0)

所有并行流都使用公共fork-join线程池,如果您提交长时间运行的任务,则可以有效地阻止池中的所有线程。因此,您将阻止使用并行流的所有其他任务。

如何确保永远不会发生这样的事情,只有两种选择。第一个是确保提交到公共fork-join池的所有任务都不会卡住并在合理的时间内完成。但说起来容易做起来难,特别是在复杂的应用程序中。另一种选择是不使用并行流并等到Oracle允许我们指定用于并行流的线程池。

用例 假设您有一个集合(List),它在应用程序启动时加载了值,并且在以后的任何时候都没有添加任何新值。在上面的场景中,您可以毫无顾虑地使用并行流。

不要担心流是高效和安全的。