Consider the following code
class Test {
public void method1() {
CompletableFuture<String> future = helloFuture();
assertEquals("done", future.get());
}
}
class Service {
@Async
public CompletableFuture<String> helloFuture() throws InterruptedException {
System.out.println("hello future");
Thread.sleep(100);
return CompletableFuture.completedFuture("done");
}
}
The helloFuture method only returns the CompletableFuture in the last line after it has done its work. But we get a reference to the returned CompletableFuture in the test method when the helloFuture starts executing and start to wait for it in the main thread (using the get method). So how does the calling method get a reference to the CompletableFuture even before it is created in the helloFuture method?
This is in the context of Spring, but even for regular ExecutorService.submit I have the same question. I guess it is possible that in a regular ExecutorService the internal implementation first creates and returns a Future object in the calling thread and queues up the task to be executed in the thread pool.
In the code you've shown, you only create the
FutureafterhelloFuturehas finished executing. There is no magic going on there: The method runs in exactly the order you think it does by reading the code. The method usesCompletableFuture.completedFuture, which does exactly what you think: It returns a newFutureinstance in an already-completed state. And thehelloFuturecall in theTestclass will block until all of that is done.