Stream.forEach()总是并行工作吗?

时间:2017-01-21 22:29:57

标签: java java-stream

Aggregating with Streams中,Brian Goetz比较使用Stream.collect()填充集合并使用Stream.forEach()执行相同操作,并使用以下两个片段:

Set<String> uniqueStrings = strings.stream()
                                   .collect(HashSet::new,
                                            HashSet::add,
                                            HashSet::addAll);

Set<String> set = new HashSet<>();
strings.stream().forEach(s -> set.add(s));

然后他解释道:

  

关键   区别在于,对于forEach()版本,多个线程正在尝试访问单个结果   容器同时使用,而使用parallel collect(),每个线程都有自己的本地结果   容器,其结果随后合并。

据我所知,只有当流是并行的时,多个线程才会在forEach()情况下工作。但是,在给出的示例中,forEach()在顺序流上运行(不调用parallelStream())。

那么,forEach()是否始终并行工作,或者代码片段应该调用parallelStream()而不是stream()。 (或者我错过了什么?)

2 个答案:

答案 0 :(得分:8)

不,如果流不是并行的,则forEach()不会并行化。我认为他为了讨论而简化了这个例子。

作为证据,此代码位于AbstractPipeline类的evaluate方法(从forEach调用)中

None

答案 1 :(得分:1)

整个报价如下:

  

正如减少可以安全地并行化,只要组合功能是关联的并且没有干扰副作用,private static final Key secret = MacProvider.generateKey(SignatureAlgorithm.HS256); private static final byte[] secretBytes = secret.getEncoded(); public static final String base64SecretBytes = Base64.getEncoder().encodeToString(secretBytes); 的可变减少可以安全地并行化,如果它满足某些简单的一致性要求(在{{1}的规范中概述) })。

然后你引用了什么:

  

关键区别在于,对于Stream.collect()版本,多个线程同时尝试访问单个结果容器,而使用并行collect(),每个线程都有自己的本地结果容器,结果之后合并。

由于第一句话清楚地提到了并行化,我的理解是在 parallel 流的上下文中都提到了forEach()collect()