我在尝试理解为什么下面这个带有.parallel()
的Java程序会引起OutOfMemoryError
,而对应的没有使用.parallel()
的程序则不会。
System.out.println(Stream
.iterate(1, i -> i+1)
.parallel()
.flatMap(n -> Stream.iterate(n, i -> i+n))
.mapToInt(Integer::intValue)
.limit(100_000_000)
.sum()
);
我有两个问题:
这个程序的预期输出是什么?
如果没有使用
.parallel()
,似乎它只会输出sum(1+2+3+...)
,这意味着它只是在 flatMap 中卡住了第一个流,这很合理。使用 parallel 时,我不知道是否有预期行为,但我猜测它以某种方式交错了前
n
个或多个流,其中n
是并行工作者的数量。基于分块/缓冲行为,它也可能略有不同。是什么导致它耗尽内存?我特别想了解这些流在幕后是如何实现的。
我猜测是某些东西阻塞了流,因此它永远无法完成并且无法摆脱生成的值,但我不太清楚评估顺序以及缓冲发生的位置。
编辑:如果有关系,我正在使用Java 11。
编辑2:显然,即使对于简单的程序 IntStream.iterate(1,i->i+1).limit(1000_000_000).parallel().sum()
,也会发生同样的情况,因此它可能与 limit
的惰性有关,而不是与 flatMap
有关。