Executor, ExecutorService, Executor - 1

"Olá, amigo!"

"Nada é perfeito quando é criado pela primeira vez. O mesmo vale para threads. Com o tempo, os criadores de Java se convenceram das deficiências da interface Runnable. Ela não suportava o lançamento de exceções e não permitia descobrir o resultado da execução de tarefas..."

"A interface Runnable é mais adequada para grandes tarefas independentes do que para pequenas subtarefas que você deseja executar uma dúzia por vez e, em seguida, coletar seus resultados."

"É por isso que a interface Callable foi inventada. Ela é muito mais adequada para execução paralela de pequenas tarefas do que Runnable e Thread, em parte porque é uma interface genérica."

"Aqui está uma implementação típica da interface:"

Exemplo
class ReverseString implements Callable<String>
{
 String str;

 ReverseString(String str)
 {
  this.str = str;
 }

 public String call() throws Exception
 {
  StringBuilder builder = new StringBuilder(str);
  builder.reverse();
  return builder.toString();
 }
}

"Ao contrário de Runnable , aqui precisamos substituir o método call, que retorna um resultado do tipo especificado pelo argumento type. Essa abordagem é muito mais conveniente do que o método run da interface Runnable, que retorna void. Às vezes, os desenvolvedores precisavam criar várias soluções alternativas para obter o resultado de um thread."

"Eu vejo."

"E agora veja como Callable pode trabalhar junto com ThreadPoolExecutor:

"Primeiro, o método submit da classe ThreadPoolExecutor retorna um objeto Future parametrizado. Você pode usar esse objeto para descobrir se uma tarefa foi concluída e obter o resultado."

"É assim que funciona:"

Exemplo
// 1. Create a ThreadPoolExecutor
ExecutorService service = Executors.newFixedThreadPool(5);

// 2. Add a task to it
Future<String> task = service.submit(new ReverseString("Amigo"));

// 3. Wait until the task is done
while(!task.isDone())
{
 Thread.sleep(1);
}

// 4. Try to get the result
//We will get either the result, or an exception if one occurred while the task was being executed
try
{
 System.out.println("Full string : " + task.get());
}
catch (Exception ie)
{
 ie.printStackTrace(System.err);
}
  
// 5. Stop the ThreadPool.
service.shutdown();

"Muito longe! Eu gosto especialmente da classe Future. Que métodos ela tem?"

"Aqui estão os mais interessantes:"

Método Descrição
boolean cancel(boolean mayInterrupt);
Interrompe a tarefa.
boolean isCancelled();
Retorna verdadeiro se a tarefa foi interrompida.
boolean isDone();
Retorna verdadeiro se a tarefa terminar de ser executada.
V get() throws InterruptedException, ExecutionException;
Retorna o resultado do método de chamada ou lança uma exceção se ocorrer.

"Legal! Então você também pode interromper as tarefas."

"Não confie muito nisso - nem todo thread pode parar. Mas se uma tarefa ainda estiver na fila, isso funcionará bem."

"Gosto dessa abordagem. É muito mais conveniente do que criar threads você mesmo e tentar obter um resultado deles."

"Ótimo. É onde vamos terminar hoje."