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()); // trueisCancelled 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()); // falseCompletionService 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()); // computedPadrã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
- ExecutorService e Tipos de Pools de Threads
- Envio de Tarefas: Runnable versus Callable
- Future e Tratamento de Erros
- ScheduledExecutorService para Tarefas Recorrentes