我在某个地方看到了使用stream().map().reduce()的代码。
这个map()函数真的可以并行工作吗?如果是,那么它可以为map()函数启动多少个最大线程数?
如果我使用parallelStream(),而不是只对下面的特定用例使用stream(),该怎么办?
有人能给我举个例子,说明在什么地方不使用parallelStream()吗?
下面的代码只是从tName中提取tCode并返回逗号分隔的字符串。
String ts = atList.stream().map(tcode -> {
return CacheUtil.getTCache().getTInfo(tCode).getTName();
}).reduce((tName1, tName2) -> {
return tName1 + ", " + tName2;
}).get();
发布于 2017-06-28 07:17:36
这个stream().map().reduce()
不是并行的,因此一个线程在流上工作。
您必须添加parallel
,或者在其他情况下添加parallelStream
(取决于API,但这是相同的)。默认情况下,使用并行方式您将得到可用处理器的数量- 1;但是主线程也在ForkJoinPool#commonPool
中使用;因此通常会有2、4、8个线程等。要检查您将得到多少个线程,请使用:
Runtime.getRuntime().availableProcessors()
您可以使用自定义池并获得任意数量的线程,如here所示。
还请注意,整个管道是并行运行的,而不仅仅是map
操作。
没有关于何时使用和何时不使用并行流的金科玉律,最好的方法是测量。但是有一些明显的选择,比如一个由10个元素组成的流--这太少了,无法从并行化中得到任何真正的好处。
发布于 2017-06-28 20:56:32
所有并行流都使用公共的叉-连接线程池,如果您提交了一个长期运行的任务,则可以有效地阻塞池中的所有线程。因此,您将阻止使用并行流的所有其他任务。
如何确保这种事情永远不会发生,只有两种选择。第一种方法是确保提交给公共叉-连接池的所有任务不会被卡住,并将在合理的时间内完成。但是说起来容易做起来难,特别是在复杂的应用程序中。另一种选择是不使用并行流,直到Oracle允许我们指定用于并行流的线程池。
用例可以说,您有一个集合(列表),它在应用程序开始时装载值,以后任何时候都不会向它添加任何新的值。在上面的场景中,您可以使用并行流而不必担心。
不要担心,流是有效和安全的。
https://stackoverflow.com/questions/44795691
复制相似问题