考虑以下使用 java 8 流的愚蠢程序:
private int biggestInt;
private void run() {
ExecutorService executor = Executors.newWorkStealingPool();
List<Callable<Integer>> callables = new ArrayList<>();
for (int i = 0; i<50; i++) {
callables.add(randomInt());
}
try {
executor.invokeAll(callables)
.stream()
.map(future -> {
try {
return future.get();
} catch (Exception e) {
throw new IllegalStateException(e);
}
})
.forEach(this::compareBiggestInt);
} catch (InterruptedException e) { /* do nothing */ }
}
private Callable<Integer> randomInt() {
return () -> {
Random random = new Random(System.currentTimeMillis());
return random.nextInt();
};
}
private void compareBiggestInt(Integer in) {
if (in > biggestInt)
biggestInt = in;
}
我的问题是,是否 forEach(this::compareBiggestInt) 是并行执行的,因此会在 biggestInt 上引入竞争条件?
如果是这样,我怎样才能避免这种竞争条件? 例如,我可以像下面这样更改方法吗?
private synchronized void compareBiggestInt(Integer in) {[...]}
感谢任何帮助!
最佳答案
不,forEach
不是并行执行的。这将打破 forEach
在与 stream()
而非 parallelStream()
一起使用时预期行为的一般约定,并且不是受您引入了 ExecutorService
这一事实的影响。
invokeAll()
实际上返回一个 List
Future
实例,已完成或超时。因此,当您与流交互时,并行部分已经完成。
关于Java 8 Streams 干扰 forEach 中的一个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44588415/