[英]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.