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