Java/Concorrência/CompletableFuture
Java⏱ ~2 min de leitura

CompletableFuture

Computação assíncrona não bloqueante

CompletableFuture, introduzido no Java 8, permite escrever código assíncrono e não bloqueante de forma fluente. Em vez de bloquear a thread aguardando um resultado, você define pipelines de transformação: o que fazer quando o resultado estiver disponível.

Os métodos principais formam um pipeline: supplyAsync executa uma tarefa assíncrona que retorna um valor, thenApply transforma o resultado (como map), thenAccept consome o resultado (como forEach), thenCompose encadeia futures dependentes, e exceptionally trata erros no pipeline. Os métodos allOf e anyOf combinam múltiplos CompletableFutures.

Por padrão, CompletableFuture usa o ForkJoinPool.commonPool(). Em aplicações com Spring Boot, @Async e Reactive Streams (WebFlux) constroem sobre esses conceitos para escalar a milhares de requisições simultâneas.

Exemplo.java
import java.util.concurrent.*;

// ── Pipeline assíncrono simples ───────────────────
CompletableFuture<String> futuro = CompletableFuture
    .supplyAsync(() -> "dados brutos")         // executa em thread separada
    .thenApply(dados -> dados.toUpperCase())   // transforma
    .thenApply(dados -> "Resultado: " + dados) // transforma novamente
    .exceptionally(ex -> "Erro: " + ex.getMessage()); // trata erros

System.out.println(futuro.get()); // Resultado: DADOS BRUTOS

// ── Encadeando operações dependentes ─────────────
CompletableFuture<String> pipeline = CompletableFuture
    .supplyAsync(() -> buscarUsuario(42))      // retorna User
    .thenCompose(user -> buscarPedidos(user))  // User → Future<List>
    .thenApply(pedidos -> "Total: " + pedidos.size())
    .exceptionally(ex -> "Falha ao carregar dados");

// ── Executar múltiplas em paralelo ────────────────
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "API 1");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "API 2");
CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> "API 3");

CompletableFuture.allOf(f1, f2, f3)
    .thenRun(() -> System.out.println("Todas concluídas!"))
    .get();
💡 Dica pro

Nunca use get() sem timeout em produção — pode bloquear para sempre se a operação travar. Use get(5, TimeUnit.SECONDS) ou orTimeout(5, TimeUnit.SECONDS).

Recompensa+50 XP+exercícios