我想从0到50范围内生成5个不同的随机数,然后并行执行一些操作。当我写这篇文章时,程序永远不会结束:
new Random().ints(0, 50)
.distinct()
.limit(5)
.parallel()
.forEach(d -> System.out.println("s: " + d));
我试图使用peek调试它。我有c:
行无限数,50 d:
行,但l:
或s:
行为零:
new Random().ints(0, 50)
.peek(d -> System.out.println("c: " + d))
.distinct()
.peek(d -> System.out.println("d: " + d))
.limit(5)
.peek(d -> System.out.println("l: " + d))
.parallel()
.forEach(d -> System.out.println("s: " + d));
我的实施有什么问题?
答案 0 :(得分:5)
首先,请注意.parallel()
更改整个管道的并行状态,因此它会影响所有操作,而不仅仅是后续操作。在你的情况下
new Random().ints(0, 50)
.distinct()
.limit(5)
.parallel()
.forEach(d -> System.out.println("s: " + d));
与
相同new Random().ints(0, 50)
.parallel()
.distinct()
.limit(5)
.forEach(d -> System.out.println("s: " + d));
您无法仅对部分管道进行并行化。它是平行还是不平行。
现在回到你的问题。由于Random.ints
是无序流,因此选择了distinct
和limit
的无序实现,因此它不是this question的副本(问题出现在有序的不同实现中)。问题在于无序limit()
实现。为了减少可能的争用,它不检查在不同线程中找到的元素的总数,直到每个子任务至少获得128个元素或上游耗尽(参见implementation,1 << 7 = 128
)。在你的情况下,上游distinct()
只发现了50个不同的元素并且拼命遍历输入以希望找到更多,但是下游limit()
没有信号停止处理,因为它想要收集至少128个检查是否达到限制之前的元素(由于限制小于128,因此不是很聪明)。所以要使这个东西工作,你应该至少选择(128 *个CPU数量)不同的元素。在使用new Random().ints(0, 512)
的4核计算机上成功,new Random().ints(0, 511)
卡住了。
为了解决这个问题,我建议按顺序收集随机数并在那里创建一个新流:
int[] ints = new Random().ints(0, 50).distinct().limit(5).toArray();
Arrays.stream(ints).parallel()
.forEach(d -> System.out.println("s: " + d));
我假设你想要执行一些昂贵的下游处理。在这种情况下,并行生成5个随机数并不是很有用。顺序执行时,此部分会更快。
更新:提交了bug report并提交了patch。
答案 1 :(得分:1)
致电ints(0, 50)
返回有效无限的伪随机int值流, 每个符合给定的原点(包括)和约束(不包括)。
我原本以为这是问题的未终止IntStream
,但我重复了这个问题。
new Random().ints(0, 50)
.distinct().limit(5)
.parallel().forEach(a -> System.out.println(a));
进入无限循环,而
new Random().ints(0, 50)
.distinct().limit(5)
.forEach(a -> System.out.println(a));
正确完成。
我的Stream知识不是很好,我可以解释它,但显然并行化并不能很好地发挥作用(可能是由于无限的流)。
答案 2 :(得分:0)
您尝试做的最接近的选择可能是使用iterate
和unordered
:
Random ran = new Random();
IntStream.iterate(ran.nextInt(50), i -> ran.nextInt(50))
.unordered()
.distinct()
.limit(5)
.parallel()
.forEach(System.out::println);
将无限流与distinct
和parallel
一起使用可能会很昂贵,或者导致无响应。有关详细信息,请参阅API Note或this question。