Java oferece duas formas de criar threads: usando a classe Thread ou a interface Runnable. Porém, Runnable não permite retornar resultados após a conclusão da thread. A interface Callable resolve esse problema, definindo um método call() que retorna um valor ao finalizar.
call()pode retornar resultados e lançar exceções, diferentemente derun()- Threads não podem ser criadas diretamente com Callable, apenas através de Runnable
import java.util.Random;
import java.util.concurrent.Callable;
class GeradorNumerico implements Callable<Integer> {
public Integer call() throws Exception {
Random rand = new Random();
int numero = rand.nextInt(5);
Thread.sleep(numero * 1000); // Simula processamento
return numero;
}
}
Interface Future
Future armazena resultados de operações assíncronas, permitindo que a thread principal acompanhe o prgoresso e recupere resultados. Principais métodos:
cancel(boolean): Interrompe a tarefaget(): Recupera o resultado (bloqueante)isDone(): Verifica conclusão
Exemplo 1: ExecutorService com Callable
import java.util.*;
import java.util.concurrent.*;
public class ExecutorCallable implements Callable<String> {
private final int id;
public ExecutorCallable(int id) {
this.id = id;
}
public static void main(String[] args) throws Exception {
final int TAREFAS = 5;
ExecutorService executor = Executors.newFixedThreadPool(TAREFAS);
List<Future<String>> resultados = new ArrayList<>();
for (int i = 0; i < TAREFAS; i++) {
resultados.add(executor.submit(new ExecutorCallable(i)));
}
executor.shutdown();
for (Future<String> f : resultados) {
System.out.println(f.get());
}
}
@Override
public String call() throws Exception {
System.out.println("Tarefa " + id + " iniciada");
long inicio = System.currentTimeMillis();
Thread.sleep(1000);
long duracao = System.currentTimeMillis() - inicio;
return "Tarefa " + id + " concluída em " + duracao + "ms";
}
}
Exemplo 2: FutureTask com Threads
import java.util.Random;
import java.util.concurrent.*;
public class FutureTaskDemo {
public static void main(String[] args) throws Exception {
FutureTask<Integer>[] tarefas = new FutureTask[5];
for (int i = 0; i < tarefas.length; i++) {
Callable<Integer> callable = new GeradorNumerico();
tarefas[i] = new FutureTask<>(callable);
new Thread(tarefas[i]).start();
}
for (FutureTask<Integer> ft : tarefas) {
System.out.println("Resultado: " + ft.get());
}
}
}
Exemplo 3: Runnable com Retorno
import java.util.Random;
import java.util.concurrent.FutureTask;
class RunnableComRetorno implements Runnable {
private Object resultado;
public void run() {
try {
Random rand = new Random();
int numero = rand.nextInt(5);
Thread.sleep(numero * 1000);
resultado = numero;
synchronized(this) {
notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized Object getResultado() throws InterruptedException {
while (resultado == null) wait();
return resultado;
}
}
public class TesteRunnable {
public static void main(String[] args) throws Exception {
RunnableComRetorno[] tarefas = new RunnableComRetorno[5];
for (int i = 0; i < tarefas.length; i++) {
tarefas[i] = new RunnableComRetorno();
new Thread(tarefas[i]).start();
}
for (RunnableComRetorno r : tarefas) {
System.out.println(r.getResultado());
}
}
}