簡體   English   中英

在並行Stream#filter中使用隨機數是否有效?

[英]Is it valid to use random numbers in parallel Stream#filter?

問題在於獲取輸入集合,對其進行隨機過濾(例如,以50%的概率包括所有元素,否則跳過它們)。 可以使用常規的for周期通過以下方式完成此操作:

Random random = new Random();
List<Object> list;    // suppose that this list is populated with some elements
List<Object> filteredList = new ArrayList<>();
for (int i  = 0; i < list.size(); ++i) {
    if (random.nextDouble() < 0.5) {
        filteredList.add(list.get(i));
    }
}

將上面的代碼重寫為Java 8流時,它看起來可能像這樣:

Random random = new Random();
List<Object> list;
List<Object> filteredList = list.stream()
    .filter(element -> random.nextDouble() < 0.5)
    .collect(Collectors.toList());

我的問題是,使用Collection#parallelStream而不是Collection#stream時,這是否是一種有效的方法? 通過有效的方法,我的主要意思是該數字實際上將是偽隨機的-在多個線程中重用同一對象是否會影響隨機性? 並且使用ThreadLocalRandom#current有所作為? 我的直覺是,重用在流外部創建的同一對象可能會產生影響,就像在filter方法中創建實例一樣

.filter(element -> ThreadLocalRandom.current().nextDouble() < 0.5)

是首選方式。 還是我缺少任何要點?

編輯:如果在filter方法中通過ThreadLocalRandom#current獲取隨機實例是正確的方法,如果我事先實例化它並使用相同的實例(如第一個代碼示例所示),將會發生什么? 從不同線程並發調用nextDouble會返回相同的數字?

從文檔中:

java.util.Random實例是線程安全的。 但是,跨線程並發使用同一java.util.Random實例可能會遇到爭用並因此導致性能下降。 考慮在多線程設計中改用ThreadLocalRandom

偽隨機性中斷的唯一情況是在具有相同種子的不同線程上初始化不同的隨機源(例如,當您使用當前時間作為種子,然后基於相同的種子創建不同的ThreadLocalRandom )。

編輯:至於在不同線程中使用相同的ThreadLocalRandom ,基本上, ThreadLocalRandom使用某種魔術來確保其從當前線程中獲取其種子(請參閱nextSeed()的實現)。

暫無
暫無

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

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