在对流进行实验时,我遇到了以下我不太理解的行为。我从迭代器创建了一个并行流,我注意到它似乎没有表现出并行性。在下面的示例中,我在控制台上打印了两个并行流的计数器,一个是从迭代器创建的,另一个是从列表创建的。从列表创建的流表现出了我预期的行为,即以非顺序顺序打印计数器,但从迭代器创建的流以顺序打印计数器。我是否错误地从迭代器创建并行流?
private static int counter = 0;
public static void main(String[] args) {
List<Integer> lstr = IntStream.rangeClosed(1, 100).boxed().collect(Collectors.toList());
Iterator<Integer> iter = lstr.iterator();
System.out.println("Iterator Stream: ");
StreamSupport.stream(Spliterators.spliteratorUnknownSize(iter, Spliterator.IMMUTABLE | Spliterator.CONCURRENT), true).forEach(i -> {
System.out.print(counter + " ");
counter++;
});
counter = 0;
System.out.println("\nList Stream: ");
lstr.parallelStream().forEach(i -> {
System.out.print(counter + " ");
counter++;
});
}
不保证并行处理以非连续顺序打印计数器。此外,由于您在没有同步的情况下更新变量,因此可能会错过其他线程所做的更新,因此结果可能完全不一致。
除此之外,还有一个Iterator
必须按顺序轮询,因此为了从并行处理中至少获得一些收益,必须缓冲元素,但如果没有已知的大小,则无法很好地估计要缓冲的元素数量。默认策略使用超过一千个元素,并且不能很好地分割工作。
因此,如果您使用超过一千个元素,您可能会注意到更多的并行活动。或者,您可以使用指定尺寸StreamSupport.stream(Spliterators.spliterator(iter, lstr.size(), 0), true)
来构造流。然后,将调整内部使用的缓冲。
尽管如此,List
的流将具有更高效的并行处理,因为它不仅知道其大小,而且支持利用底层数据结构的随机访问性质分割工作负载。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)