gpt4 book ai didi

java - 对连续的 java CompletionStages 之间的共享上下文对象所做的最新更改是否始终对执行 lambda 的每个线程可见

转载 作者:行者123 更新时间:2023-12-05 05:52:35 25 4
gpt4 key购买 nike

package org.stackoverflow.example;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MeetPlay {

private static final class Context {
List<String> data = new ArrayList<>();
}

public static void main(String[] args) {

ExecutorService executor = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors());

Context context = new Context();
CompletableFuture.completedFuture(context)
.thenAcceptAsync(c -> context.data.add("1"), executor)
.thenAcceptAsync(__ -> context.data.add("2"), executor)
.thenAcceptAsync(__ -> {
if (context.data.contains("1") && context.data.contains("2")) {
System.out.println("Will that always be the case");
} else {
System.out.println("Or not");
}
}, executor);
}
}

我目前的理解是,上面的代码将始终打印:“Will that always the case”,无论执行者使用多少线程、涉及多少阶段和项目,或者 Context 对象有多“复杂”(例如,有更多嵌套字段),由于 Java 完成阶段之间的保证发生之前。

工作中的一位同事认为这并不能保证,并说他已经通过经验证明了这一点,但是,我还没有亲眼看到。在那之前,我想知道你们怎么想,最重要的是为什么。引用资料将不胜感激!

编辑:问题是关于共享上下文的内存可见性保证,而不是每个阶段是否在前一个阶段完成后执行。

最佳答案

你是对的 - 这些阶段是按顺序执行的。这可以通过运行这段代码来证明:

    CompletableFuture.completedFuture(context)
.thenAcceptAsync(c -> {
context.data.add("1");
System.out.println("1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}, executor)
.thenAcceptAsync(__ -> {
context.data.add("2");
System.out.println("2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}, executor)
.thenAcceptAsync(__ -> {
if (context.data.contains("1") && context.data.contains("2")) {
System.out.println("Will that always be the case");
} else {
System.out.println("Or not");
}
}, executor);

结果将是:

1
(pause 1 sec)
2
(pause 1 sec)
Will that always be the case

发生这种情况是因为从 thenAcceptAsync 返回的 CompletionStage 仅在操作完成后才完成。 IE。如果操作异常完成,CompletionStage 也会异常完成。此行为与 thenAccept 相同。 thenAcceptAsync 中的“Async”仅表示该操作将使用另一个执行程序执行。

如果您想要并行执行,请考虑以下代码:

    CompletableFuture<Context> f = CompletableFuture.completedFuture(context);
f.thenAcceptAsync(c -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
context.data.add("1");
System.out.println("1");
}, executor);
f.thenAcceptAsync(__ -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
context.data.add("2");
System.out.println("2");
}, executor);
f.thenAcceptAsync(__ -> {
if (context.data.contains("1") && context.data.contains("2")) {
System.out.println("Will that always be the case");
} else {
System.out.println("Or not");
}
}, executor);

这里3个阶段加到同一个阶段,不是一个接一个。一个阶段的完成和另一个阶段的开始之间没有依赖关系。所以阶段可以并行执行。结果将是:

Or not
(pause 1 sec)
2
1

关于java - 对连续的 java CompletionStages 之间的共享上下文对象所做的最新更改是否始终对执行 lambda 的每个线程可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70098669/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com