When you say you want to know whether "a completablefuture can be run in the thread in which it was created", you are exhibiting a wrong mindset. A CompletableFuture doesn't run. A CompletableFuture just encapsulates a value or exception, which can be set at most one time, which we call completing it.
The API offers a lot of methods for scheduling completion attempts, potentially asynchronous, but you shouldn't get distracted from the fact that you decide how to complete it.
There are simple alternatives to asynchronous completion:
CompletableFuture<String> f = CompletableFuture.completedFuture("hello");
creates an immediately completed future. Java 9 adds failedFuture to support creating an immediately exceptionally completed future.
You can also easily create a future to be completed at a later time within the same thread:
CompletableFuture<String> f = new CompletableFuture<>();
// arbitrary actions
f.complete("hello");
You can also use the factory methods with an executor, immediately running the action in the initiating thread:
CompletableFuture<String> f
= CompletableFuture.supplyAsync(() -> "hello", Runnable::run);
or
CompletableFuture<String> f
= CompletableFuture.supplyAsync(() -> {
if(Math.random() > 0.5) throw new IllegalStateException();
return "hello";
}, Runnable::run);
to demonstrate the difference to an invocation of complete or creating an immediately completed future.
Of course, these possibilities can be combined with the other features, like allOf:
CompletableFuture<String> a = new CompletableFuture<>();
CompletableFuture<String> b = new CompletableFuture<>();
CompletableFuture<String> c = new CompletableFuture<>();
CompletableFuture.allOf(a, b, c).whenComplete((__, t) -> {
if(t != null) System.err.println("failed with "+t);
else System.out.println("all completed "+a.join()+", "+b.join()+", "+c.join());
});
System.out.println("step 1");
a.complete("foo");
System.out.println("step 2");
b.complete("bar");
System.out.println("step 3");
c.complete("baz");