I have a question about CompletableFuture method:
public CompletableFuture thenApply(Function super T, ? extends U> fn)
The policies as specified in the CompletableFuture docs could help you understand better:
Actions supplied for dependent completions of non-async methods may be performed by the thread that completes the current CompletableFuture, or by any other caller of a completion method.
All async methods without an explicit Executor argument are performed using the
ForkJoinPool.commonPool()(unless it does not support a parallelism level of at least two, in which case, a new Thread is created to run each task). To simplify monitoring, debugging, and tracking, all generated asynchronous tasks are instances of the marker interfaceCompletableFuture.AsynchronousCompletionTask.
Update: I would also advice on reading this answer by @Mike as an interesting analysis further into the details of the documentation.