Vamos analisar a inicialização e a composição de computações assíncronas com
CompletableFuture: como iniciar tarefas via
supplyAsync e
runAsync, em que os handlers
thenApply,
thenAccept,
thenRun diferem, e quando escolher suas versões assíncronas
thenApplyAsync/
thenAcceptAsync/
thenRunAsync. Vamos falar sobre threads de execução (
ForkJoinPool ou seu
Executor), tipos de resultados (
CompletableFuture<T>,
CompletableFuture<Void>) e erros típicos: chamadas bloqueantes
get()/
join(), erros não tratados sem
exceptionally/
handle/
whenComplete, bem como a tentativa de usar o resultado dentro de
thenRun.