簡體   English   中英

對於Stream.generate(foo).parallel(),foo必須是線程安全的嗎?

[英]For Stream.generate(foo).parallel(), does foo have to be thread safe?

我正在使用Java 8 Streams。 我有一個自定義函數foo() ,它產生一個對象,我想並行傳輸它創建的對象。 我知道foo()不是線程安全的。

如果我寫Stream.generate(foo).parallel() ,會以異步方式調用foo()嗎? 即,對象是串行生成的,並傳遞給並行線程,還是多個線程通過調用foo()根據需要生成對象?

如您可以通過快速實驗觀察到的,將從多個線程調用供應商:

Stream.generate(() -> Thread.currentThread().getId())
    .parallel()
    .limit(100000)
    .distinct()
    .forEach(System.out::println);

雖然數據爭用不是保證行為,但以下代碼

System.out.println(
    Stream.generate(new Supplier<Integer>() {
        int i; @Override public Integer get() { return i++; }
    }).parallel()
      .limit(10_000)
      .collect(BitSet::new, BitSet::set, BitSet::or)
      .cardinality()
);

在我的環境中可重復打印小於10,000的數字,證明當供應商不是線程安全時,確實可能發生缺失更新。

請注意,供應商也可能需要查詢比結果評估所需的元素更多的元素。 例如

LongAdder adder = new LongAdder();
System.out.println(
    Stream.generate(new Supplier<Integer>() {
        int i; @Override public Integer get() { adder.increment(); return i++; }
    }).parallel()
      .limit(10_000)
      .collect(BitSet::new, BitSet::set, BitSet::or)
      .cardinality()
);
System.out.println("queried "+adder+" times");

通常報告大量超過10,000的查詢,同時,由於數據競爭,結果報告少於10,000個不同的元素。

使供應商線程安全,將結果更改為10,000個不同元素的正確數量,但供應商仍可查詢超過10,000次,因此,結果不能保證包含0到9,999之間的數字,因為流通過generate創建的是無序的 ,因此可以使用來自供應商的任何10,000個不同的數字。

暫無
暫無

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

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