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);
}
}
我目前的理解是,上面的代码将始终打印:“无论执行器使用多少线程、涉及多少阶段和项目,或者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仅在操作完成后完成。也就是说,如果操作异常完成,那么CompletionStage也会完成。此行为与thenAccep相同。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
问题内容: 我正在使用Python模块(PyCLIPS)和Django 1.3。 我想开发一个线程安全类,该类可实现对象池和Singleton模式,并且还必须在Django中的请求之间共享。 例如,我要执行以下操作: 请求从池中获取具有某些ID的对象,对其进行处理,然后将其推回池中,然后发送带有对象ID的响应。 另一个具有对象ID的请求从池中获取具有给定ID的对象,并重复上述请求中的步骤。 但是对
问题内容: 通过回答此问题,可以回答所有其他三个问题。希望我能说清楚: 在通过多处理创建的某些过程中创建对象后: 如何将对该对象的 引用 传递给其他进程? (不是很重要)我如何确保持有参考书时此过程不会消失? 示例1(已解决) 例子2 假设返回一个具有可变状态的对象。这个相同的对象应该可以从其他进程访问。 例子3 我有一个带有打开文件和锁的对象-如何授予对其他进程的访问权限? 提醒 我不希望此特定
我有一个节点类,它包含两个嵌套类,服务器和客户机,以及指向每个类实例的指针。 我的猜测是上下文切换正在发生,因此每个进程都有自己的副本被加载到相同的地址中。 我如何改变这一点,使每个进程访问该节点的完全相同的副本? 更新:
问题内容: 我对进程之间具有文件句柄的共享资源有疑问。这是我的测试代码: 然后我得到如下图所示: 我认为当我将对象放入队列时,对象被序列化了,而文件句柄无法序列化,所以,我得到了: 有人对此有任何想法吗?如果要共享具有文件句柄属性的对象,该怎么办? 问题答案: 我不得不反对(总之,不仅仅会放在注释中;-) @Mark反复断言文件句柄不能“在运行的进程之间传递”-这在现实,现代中根本不是真的操作系统
我是Java新手,我想为每个现有和每个新对象更改一个类变量,而无需遍历每个对象。 这里的class变量是handlingFee,我在另一个类中有一个集合(ArrayList)来存储这些类对象。这有可能吗? 那么你能告诉我如何改变这个值吗?我必须迭代每个对象吗?
我创建了一个可运行的类a,它为我执行一些任务。我使用ExecutorService提交这个类,以便并行执行这些任务。 可运行类A调用另一个对象B,该对象发送一个AsyncFuture请求(future.get()one)。 我将可运行类A的单独对象提交给ExecutorService,但是,类B的对象由bean(单例)引用。这会导致线程执行出现问题吗? 我注意到类A的一些对象没有被任何线程执行。