Executor, ExecutorService, Executor - 1

"Ciao, Amico!"

"Niente è perfetto quando viene creato per la prima volta. Lo stesso vale per i thread. Col tempo, i creatori di Java si sono convinti delle carenze dell'interfaccia Runnable. Non supportava il lancio di eccezioni e non rendeva possibile scoprire il risultato dell'esecuzione di compiti…”

"L'interfaccia Runnable è più adatta per grandi attività indipendenti che per piccole attività secondarie che si desidera eseguire una dozzina alla volta e quindi raccogliere i risultati."

"Ecco perché è stata inventata l' interfaccia Callable . È molto più adatta per l'esecuzione parallela di piccole attività rispetto a Runnable e Thread, in parte perché è un'interfaccia generica."

"Ecco un'implementazione tipica dell'interfaccia:"

Esempio
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();
 }
}

"A differenza di Runnable , qui dobbiamo sovrascrivere il metodo call, che restituisce un risultato del tipo specificato dall'argomento type. Questo approccio è molto più conveniente del metodo run dell'interfaccia Runnable, che restituisce void. A volte gli sviluppatori dovevano inventare varie soluzioni alternative per ottenere il risultato di un thread."

"Vedo."

"E ora guarda come Callable può lavorare insieme a ThreadPoolExecutor:

"In primo luogo, il metodo submit della classe ThreadPoolExecutor restituisce un oggetto Future parametrizzato. È possibile utilizzare questo oggetto per scoprire se un'attività è terminata e per ottenere il risultato."

"Ecco come funziona:"

Esempio
// 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();

"Lontano! Mi piace particolarmente la classe Future. Che metodi ha?"

"Ecco i più interessanti:"

Metodo Descrizione
boolean cancel(boolean mayInterrupt);
Arresta l'attività.
boolean isCancelled();
Restituisce true se l'attività è stata interrotta.
boolean isDone();
Restituisce true se l'attività è stata eseguita.
V get() throws InterruptedException, ExecutionException;
Restituisce il risultato del metodo di chiamata o genera un'eccezione se ne è verificata una.

"Fantastico! Quindi puoi anche interrompere le attività."

"Non fare troppo affidamento su questo, non tutti i thread possono interrompersi. Ma se un'attività è ancora in coda, funzionerà correttamente."

"Mi piace questo approccio. È molto più conveniente che creare thread da soli e poi provare a tirarne fuori un risultato."

"Fantastico. Ecco dove finiremo oggi."