A CompletableFuture is completed with a value, then thenApplyAsync is called without supplying an Executor. Which thread runs the function, and why is this a common production gotcha?
CompletableFuture<Integer> done = CompletableFuture.completedFuture(7);
done.thenApplyAsync(x -> heavyWork(x)); // no executor arg