Banale esempio di utilizzo dell'interfaccia Future a cura di Flavio Casadei Della Chiesa

Esempio future

In questa pagina si vuole descrivere il funzionamento dell'interfaccia 'java.util.concurrent.Future'. Le API Java 5 dicono che un Future rappresenta il risultato di una computazione asincrona, …, il risultato può essere recuperato con il metodo get solamente quando la computazione è completata, eventualmente bloccando il chiamante fino a quando il risultato non è pronto.

Esempio

In questo esempio si vogliono testare due processori 'p1' e 'p2' e si da loro da calcolare un risultato. Il testa ha successo se entrambi i processori danno lo stesso risultato altrimenti fallisce. Il calcolo del risultato è piuttosto complesso, si delega quindi ad un esecutore l'esecuzione del calcolo su entrambi i processori e si aspetta che questo abbia finito prima di confrontare i risultati. 'NOTA: l'esempio è assai semplice: non ci sono calcoli complicati, c'è solo un random che può far guastare un processore'.

 
 
package test.esecutore;
/**
 * Usare solo a scopo didattico!
 */
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import junit.framework.TestCase;
 
public class TestFuture extends TestCase { 
	//valore atteso dal calcolo
	private static final  Double CLEAN = 1.0;
	//probabilità di successo del primo procesore
	private static final  double okProb1 = 0.6;
	//probabilità di successo del secondo processore
	private static final  double okProb2 = 0.65;
	public void testFoo() throws Exception{
		//Esecutore dei task
		Executor executor = new ThreadPerTaskExecutor();
		//Future del primo processore
		FutureTask<Double> proc1 =
			new FutureTask<Double>(new Callable<Double>() {
				public Double call() throws InterruptedException {
					Double retval = CLEAN;
					double d = Math.random();
					if ( d > okProb1) {
						retval = d;
					}
								Thread.sleep(  (long)Math.floor(d*500 )  );
 
					return retval;
				}});
//		Future del secondo processore
		FutureTask<Double> proc2 =
			new FutureTask<Double>(new Callable<Double>() {
				public Double call() throws InterruptedException {
					Double retval = CLEAN;
					double d = Math.random();
					if ( d > okProb2) {
						retval = d;
					}
					Thread.sleep(  (long)Math.floor(d*500 )  );
					return retval;
				}});
		//eseguo in modo asincrono entrambi i calcoli
		executor.execute(proc1);
		executor.execute(proc2);
		//prendo i risultati
		Double p1 = proc1.get();
		Double p2 = proc2.get();
		// li confronto
		assertEquals(p1, p2);
	}
 
 
	//Semplice esecutore asincrono. Non usare in produzione!!!!!
	class ThreadPerTaskExecutor implements Executor {
		public void execute(Runnable r) {
			new Thread(r).start();
		}
	}
 
 
}