0Pricing
Java Academy · Aula

Envio de Tarefas: Runnable versus Callable

Envie tarefas Runnable e Callable e recupere os resultados por meio de Future.

Envio de Tarefas: Runnable versus Callable é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 2 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.

Executável versus chamável

Duas interfaces funcionais representam tarefas enviadas ao ExecutorService:

  • Executável: não retorna um valor e não pode declarar exceções verificadas
  • Chamável<V>: retorna um resultado do tipo V e pode lançar exceções verificadas
import java.util.concurrent.*;

// Runnable — no return value
Runnable r = () -> System.out.println("Running");

// Callable<Integer> — returns a value
Callable<Integer> c = () -> {
    return 42; // or do computation
};

submit(Executável)

submit(Runnable) retorna um Future<?>. Chamar get() nele retorna nulo, mas confirma que a tarefa foi concluída, ou lança uma exceção se ela tiver falhado.

ExecutorService pool = Executors.newFixedThreadPool(2);

Future<?> future = pool.submit(() ->
    System.out.println("Task done on " + Thread.currentThread().getName())
);

future.get(); // waits for completion; returns null
System.out.println("Task confirmed complete");
pool.shutdown();

submit(Chamável&lt;V&gt;)

submit(Callable) retorna um Future<V>. Chame future.get() para recuperar o resultado; a chamada bloqueia até a conclusão.

ExecutorService pool = Executors.newFixedThreadPool(2);

Callable<Integer> sumTask = () -> {
    int sum = 0;
    for (int i = 1; i <= 100; i++) sum += i;
    return sum;
};

Future<Integer> future = pool.submit(sumTask);
Integer result = future.get(); // blocks until done
System.out.println("Sum 1..100 = " + result); // 5050
pool.shutdown();

Envio de vários chamáveis com invokeAll

invokeAll() envia uma coleção de chamáveis e retorna uma lista de futuros; todos são concluídos antes do retorno:

List<Callable<String>> tasks = List.of(
    () -> "Result A",
    () -> "Result B",
    () -> "Result C"
);

ExecutorService pool = Executors.newFixedThreadPool(3);
List<Future<String>> futures = pool.invokeAll(tasks);

for (Future<String> f : futures) {
    System.out.println(f.get());
}
pool.shutdown();

invokeAny: primeiro resultado bem-sucedido

invokeAny() envia uma coleção de chamáveis e retorna o resultado do primeiro que for concluído com sucesso, cancelando os demais:

List<Callable<String>> candidates = List.of(
    () -> { Thread.sleep(200); return "Slow"; },
    () -> { Thread.sleep(50);  return "Fast"; },
    () -> { Thread.sleep(100); return "Medium"; }
);

ExecutorService pool = Executors.newFixedThreadPool(3);
String winner = pool.invokeAny(candidates);
System.out.println("First: " + winner); // Fast
pool.shutdown();

execute() versus submit()

execute(Runnable) dispara a tarefa e não acompanha o resultado: nenhum Future é retornado, e as exceções são perdidas, a menos que você adicione um manipulador de exceções não capturadas. submit() encapsula a tarefa em um Future, capturando as exceções para recuperação por meio de get().

ExecutorService pool = Executors.newFixedThreadPool(2);

// execute: exception silently lost
pool.execute(() -> { throw new RuntimeException("Oops!"); });

// submit: exception captured in Future
Future<?> f = pool.submit(() -> { throw new RuntimeException("Oops!"); });
try {
    f.get();
} catch (ExecutionException e) {
    System.out.println("Caught: " + e.getCause().getMessage());
}
pool.shutdown();

Chamável com exceções verificadas

Ao contrário do executável, o chamável pode lançar exceções verificadas, o que o torna adequado para operações de E/S e de banco de dados:

Callable<String> dbQuery = () -> {
    // This compiles fine — checked exception is declared on Callable.call()
    if (Math.random() < 0.5) throw new java.sql.SQLException("DB error");
    return "row data";
};

Future<String> f = pool.submit(dbQuery);
try {
    String data = f.get();
} catch (ExecutionException e) {
    if (e.getCause() instanceof java.sql.SQLException) {
        System.out.println("DB failed: " + e.getCause().getMessage());
    }
}

Paralelização de computações independentes

Use vários envios de chamáveis para executar computações independentes em paralelo:

ExecutorService pool = Executors.newFixedThreadPool(4);

Future<Long> sumFuture  = pool.submit(() -> LongStream.rangeClosed(1,1_000_000).sum());
Future<Long> prodFuture = pool.submit(() -> LongStream.rangeClosed(1,20).reduce(1L, (a,b)->a*b));

long sum  = sumFuture.get();
long prod = prodFuture.get();
System.out.println("Sum: " + sum + ", 20!: " + prod);
pool.shutdown();

Agregação de resultados de chamáveis

Envie muitas tarefas e agregue os resultados quando todas estiverem concluídas:

int N = 8;
ExecutorService pool = Executors.newFixedThreadPool(N);
List<Future<Integer>> futures = new ArrayList<>();

for (int i = 0; i < N; i++) {
    final int chunk = i;
    futures.add(pool.submit(() -> chunk * chunk)); // i^2
}

int total = 0;
for (Future<Integer> f : futures) total += f.get();
System.out.println("Sum of squares: " + total);
pool.shutdown();

Tempo limite para um chamável

Informe um tempo limite a future.get(timeout, unit) para evitar esperar indefinidamente:

Future<String> f = pool.submit(() -> {
    Thread.sleep(5000); // slow task
    return "done";
});
try {
    String result = f.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
    System.out.println("Task timed out");
    f.cancel(true); // interrupt the task
} catch (ExecutionException e) {
    System.out.println("Task failed: " + e.getCause());
}

Práticas recomendadas

Resumo das práticas recomendadas:

  • Prefira submit() a execute(): as exceções são capturadas
  • Use um chamável quando precisar de um valor de retorno ou de exceções verificadas
  • Sempre chame future.get() com um tempo limite
  • Use invokeAll para processamento em lote e invokeAny quando o primeiro resultado deve prevalecer
  • Sempre encerre o pool

Verificação rápida

Qual é a principal vantagem de um chamável em relação a um executável?

Recapitulação: executável versus chamável

Principais conclusões:

  • Executável: void, sem exceções verificadas; submit retorna Future<?> nulo
  • Chamável: retorna V e pode lançar exceções verificadas; submit retorna Future<V>
  • invokeAll: envia um lote e espera todas as tarefas terminarem
  • invokeAny: retorna o primeiro resultado bem-sucedido e cancela os demais
  • Sempre use submit() para capturar exceções

Perguntas Frequentes

A aula “Envio de Tarefas: Runnable versus Callable” é grátis?

Sim — o texto completo de “Envio de Tarefas: Runnable versus Callable” é 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 “Envio de Tarefas: Runnable versus Callable”?

Envie tarefas Runnable e Callable e recupere os resultados por meio de Future. 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 2 de 4.

Quanto tempo leva a aula “Envio de Tarefas: Runnable versus Callable”?

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