簡體   English   中英

在並行Java流中處理隨機數

[英]Processing random numbers in parallel Java stream

我想從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));

我的實施有什么問題?

首先,請注意.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是一個無序流,因此選擇了distinctlimit無序實現,因此它不是這個問題的重復(問題出現在有序的不同實現中)。 這里的問題在於無序的limit()實現。 為了減少可能的爭用,它不檢查在不同線程中找到的元素的總數,直到每個子任務獲得至少128個元素或上游耗盡(參見實現1 << 7 = 128 )。 在你的情況下,上游distinct()發現只有50個不同的元素,拼命遍歷輸入,希望找到更多,但下游limit()不發信號停止處理,因為它想要在檢查之前是否收集至少128個元素達到限制(由於限制小於128,因此不是很聰明)。 所以要使這個東西工作,你應該至少選擇(128 *個CPU數量)不同的元素。 在我的4核機器上使用new Random().ints(0, 512)成功,而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個隨機數並不是很有用。 順序執行時,此部分將更快。

更新:提交了錯誤報告並提交了補丁

你的ints(0, 50)電話( 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知識不是很好,我可以解釋它,但顯然並行化不能很好地發揮作用(可能是由於無限的流)。

您嘗試做的最接近的選擇可能是使用iterateunordered

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注釋此問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM