In Java dalla versione 1.0 è presente l'interfaccia java.lang.Runnable, che come sappiamo deve essere implementata da quelle classi che si vuole eseguire come Thread separati.
Nell'interfaccia è dichiarato un solo metodo
void run()
Dalla versione 1.5 invece è stata creata una nuova interfaccia java.util.concurrent.Callable che per certi versi può essere vista come una estensione dell'interfaccia Runnable. Lo scopo dei progettisti è sempre quello di mantenere la retrocompatibilità, e questo è il motivo per cui non hanno modificato l'interfaccia Runnable ma ne hanno creata una nuova.
L'unico metodo definito dall'interfaccia Callable è:
V call() throws Exception
Il vantaggio di utilizzare Callable è che consente di ottenere indietro il risultato dell'esecuzione del task nel thread separato, cosa che tramite Runnable non è possibile.
In generale le differenze tra le 2 interfacce sono le seguenti:
Per utilizzare un oggetto che implementa un Callable dobbiamo necessariamente utilizzare un ExecutorService.
CALLABLE
Si noti che l'executor service funziona anche con oggetti di tipo Runnable ma, poichè questi non tornano un risultato, il Future associato tornerà null se il processo è terminato correttamente.
Nell'interfaccia è dichiarato un solo metodo
void run()
Dalla versione 1.5 invece è stata creata una nuova interfaccia java.util.concurrent.Callable che per certi versi può essere vista come una estensione dell'interfaccia Runnable. Lo scopo dei progettisti è sempre quello di mantenere la retrocompatibilità, e questo è il motivo per cui non hanno modificato l'interfaccia Runnable ma ne hanno creata una nuova.
L'unico metodo definito dall'interfaccia Callable è:
V call() throws Exception
Il vantaggio di utilizzare Callable è che consente di ottenere indietro il risultato dell'esecuzione del task nel thread separato, cosa che tramite Runnable non è possibile.
In generale le differenze tra le 2 interfacce sono le seguenti:
- Un oggetto che implementa Callable non può essere utilizzato direttamente per costruire un Thread, mentre un oggetto che implementa Runnable può farlo;
- Un oggetto che implementa Callable torna un risultato mentre un oggetto che implementa Runnable no;
- Un oggetto che implementa Callable può rilanciare al chiamante una eccezione di tipo checked, mentre un oggetto che implementa Runnable può lanciare soltanto unchecked exceptions.
Per utilizzare un oggetto che implementa un Callable dobbiamo necessariamente utilizzare un ExecutorService.
CALLABLE
import java.util.concurrent.Callable;
public class Fattoriale implements Callable<Long> {
private long n;
public Fattoriale(long n){
this.n=n;
}
@Override
public Long call() throws Exception {
if(n<=0) throw new Exception("Attenzione inserire un valore positivo!!");
long f=1;
for(long i=1;i<=n;i++){
f*=i;
}
return f;
}
}
EXECUTORSERVICE
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class FattorialeTest {
public static void main(String[] args) throws Exception {
long N=5;
Callable<Long> c=new Fattoriale(N);
ExecutorService es=Executors.newSingleThreadExecutor();
Future<Long> f=es.submit(c);
System.out.println(String.format("Il fattoriale di %d è %d",N,f.get()));
es.shutdown();
}
}
Si noti che l'executor service funziona anche con oggetti di tipo Runnable ma, poichè questi non tornano un risultato, il Future associato tornerà null se il processo è terminato correttamente.
Nessun commento:
Posta un commento