0Pricing
Java Academy · Aula

Future e Tratamento de Erros

Use Future.get com limites de tempo, trate ExecutionException e cancele tarefas em execução.

Future e Tratamento de Erros é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.

O que é um futuro?

Um Future<V> representa o resultado pendente de uma computação assíncrona. Ele oferece métodos para verificar a conclusão, esperar pelo resultado e tratar erros.

import java.util.concurrent.*;

ExecutorService pool = Executors.newFixedThreadPool(2);
Future<Integer> future = pool.submit(() -> {
    Thread.sleep(1000);
    return 42;
});

System.out.println("Is done? " + future.isDone()); // false
Integer result = future.get(); // blocks
System.out.println("Result: " + result); // 42
pool.shutdown();

future.get() com tempo limite

Sempre prefira a variante com tempo limite para evitar ficar aguardando indefinidamente:

try {
    Integer result = future.get(5, TimeUnit.SECONDS);
    System.out.println(result);
} catch (TimeoutException e) {
    System.out.println("Timed out");
    future.cancel(true); // interrupt the task
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
} catch (ExecutionException e) {
    System.out.println("Task threw: " + e.getCause());
}

ExecutionException

Se a tarefa tiver lançado uma exceção, future.get() a encapsulará em ExecutionException. Remova esse encapsulamento com getCause():

Future<String> failing = pool.submit(() -> {
    throw new IllegalArgumentException("bad input");
});

try {
    failing.get();
} catch (ExecutionException e) {
    Throwable cause = e.getCause();
    System.out.println(cause.getClass().getSimpleName()); // IllegalArgumentException
    System.out.println(cause.getMessage()); // bad input
}

Cancelamento de um futuro

cancel(mayInterruptIfRunning) tenta cancelar a tarefa. Retorna true se tiver sucesso. Se mayInterruptIfRunning for true, uma interrupção será enviada à thread em execução.

Future<String> f = pool.submit(() -> {
    try {
        Thread.sleep(10_000); // long task
        return "done";
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        return "interrupted";
    }
});

boolean cancelled = f.cancel(true); // send interrupt
System.out.println("Cancelled: " + cancelled); // true
System.out.println("Is cancelled: " + f.isCancelled()); // true

isCancelled versus isDone

isDone() retorna true se a tarefa tiver sido concluída normalmente, lançado uma exceção ou sido cancelada. isCancelled() retorna true apenas se ela tiver sido cancelada.

// After cancel:
System.out.println(f.isDone());       // true
System.out.println(f.isCancelled()); // true

// After normal completion:
Future<Integer> done = pool.submit(() -> 5);
done.get(); // wait
System.out.println(done.isDone());       // true
System.out.println(done.isCancelled()); // false

CompletionService para resultados disponíveis primeiro

ExecutorCompletionService encapsula um pool e oferece um método take() para recuperar o próximo Future concluído, na ordem de conclusão, não na ordem de envio:

ExecutorCompletionService<Integer> cs =
    new ExecutorCompletionService<>(pool);

for (int i = 0; i < 5; i++) {
    final int delay = 5 - i; // submit fastest last
    cs.submit(() -> { Thread.sleep(delay * 100); return delay; });
}

for (int i = 0; i < 5; i++) {
    Future<Integer> f = cs.take(); // next completed
    System.out.println(f.get());
}

Tratamento seguro de vários futuros

Ao coletar resultados de muitos futuros, percorra-os e trate as exceções individualmente:

List<Future<String>> futures = new ArrayList<>();
for (int i = 0; i < 5; i++) {
    final int id = i;
    futures.add(pool.submit(() ->
        id % 2 == 0 ? "ok_" + id : (() -> { throw new RuntimeException("fail_"+id); }).get()
    ));
}

for (Future<String> f : futures) {
    try {
        System.out.println(f.get());
    } catch (ExecutionException e) {
        System.out.println("Error: " + e.getCause().getMessage());
    }
}

Future.get() após o encerramento do pool

Enviar uma tarefa depois de shutdown() lança RejectedExecutionException. No entanto, os futuros enviados ANTES do encerramento ainda podem ser recuperados depois dele:

ExecutorService pool2 = Executors.newFixedThreadPool(2);
Future<Integer> f = pool2.submit(() -> 99);
pool2.shutdown(); // no new tasks

// Still valid — task was submitted before shutdown:
System.out.println(f.get()); // 99

try {
    pool2.submit(() -> 0); // throws!
} catch (RejectedExecutionException e) {
    System.out.println("Pool shut down");
}

FutureTask: futuro manual

FutureTask<V> implementa tanto Runnable quanto Future<V>, sendo útil quando você precisa de um Future sem um ExecutorService:

FutureTask<String> task = new FutureTask<>(() -> "computed");
new Thread(task).start(); // run in any thread
System.out.println(task.get()); // computed

Padrão de novas tentativas com um futuro

Implemente uma lógica simples de novas tentativas em torno de future.get():

Future<String> future = pool.submit(() -> {
    if (Math.random() < 0.7) throw new RuntimeException("transient error");
    return "success";
});

for (int attempt = 0; attempt < 3; attempt++) {
    try {
        System.out.println(future.get());
        break;
    } catch (ExecutionException e) {
        System.out.println("Attempt " + (attempt+1) + " failed");
        if (attempt == 2) throw e;
        future = pool.submit(() -> "retry"); // resubmit
    }
}

Limitações de um futuro

java.util.concurrent.Future tem limitações:

  • Não há retornos de chamada: é necessário bloquear com get()
  • Não é possível encadear transformações
  • Não é possível combinar vários futuros

Use CompletableFuture (no próximo curso) para obter uma composição reativa e sem bloqueio.

Verificação rápida

Uma tarefa lança uma exceção. Quando você chama future.get(), qual exceção é lançada?

Recapitulação: futuro e tratamento de erros

Principais conclusões:

  • future.get() bloqueia; sempre use a variante com tempo limite
  • ExecutionException encapsula as exceções da tarefa; remova o encapsulamento com getCause()
  • cancel(true) envia uma interrupção; isDone/isCancelled informam o estado
  • ExecutorCompletionService.take() recupera os futuros na ordem de conclusão
  • FutureTask implementa tanto Runnable quanto Future

Perguntas Frequentes

A aula “Future e Tratamento de Erros” é grátis?

Sim — o texto completo de “Future e Tratamento de Erros” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.

O que vou aprender em “Future e Tratamento de Erros”?

Use Future.get com limites de tempo, trate ExecutionException e cancele tarefas em execução. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Java Academy?

Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Future e Tratamento de Erros”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Java Academy?

Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. ExecutorService e Tipos de Pools de Threads
  2. Envio de Tarefas: Runnable versus Callable
  3. Future e Tratamento de Erros
  4. ScheduledExecutorService para Tarefas Recorrentes
← Voltar para Java Academy