Java 8 Streams 干扰 forEach 中的一个字段

标签 java concurrency java-8 java-stream

考虑以下使用 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/

相关文章:

Java 同步和在文本 Pane 中写入

java - 使用 java 8 流从内部列表中检索数据

java - 仅基于选定的微调项设置文本值

java - 使用 PDFBox 将页面添加到 PDF/A 文件,而不会丢失 PDF/A 的有效性

java - 发送十六进制命令到 ESC/POS 打印机 Android

multithreading - 阐明 OpenSSL 0.9.8L 并发支持 - 如果非并发完成,SSL 实例能否被多个线程使用?

java - 使用多线程递增/递减/打印(代码审查)

java - Eclipse插件,自定义运行命令

java - 使用 Stream 读取文件并跟踪当前索引

java - 从 Java Stream of Map 中按键将它们分组并找到最大值不按预期工作