我在某处使用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();
答案 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),它在应用程序启动时加载了值,并且在以后的任何时候都没有添加任何新值。在上面的场景中,您可以毫无顾虑地使用并行流。
不要担心流是高效和安全的。