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);
}
}
My current understanding is that code above will always print: "Will that always be the case" no matter how many threads the executor uses, stages and items are involved, or how "complex" the Context object is (e.g. with more nested fields), due to the happens before guarantee between java completion stages.
A colleague at work argues that is not guaranteed and says he has empirically proven it, however, I haven't actually seen it with my own eyes. Until that happens, I was wondering what do you guys think and most importantly WHY. References will be greatly appreciated!
EDIT: question is regarding the memory visibility guarantees around the shared context and not whether each stage is executed after the previous completes.