Java Callable Future Beispiel
Java Callable und Future werden häufig in der multithreaded Programmierung verwendet. In den letzten Beiträgen haben wir viel über Java Threads gelernt, aber manchmal wünschen wir uns, dass ein Thread einen Wert zurückgeben könnte, den wir nutzen können. Java 5 führte das java.util.concurrent.Callable Interface im Concurrency-Paket ein, das ähnlich wie das Runnable Interface ist, aber es kann jedes Objekt zurückgeben und eine Ausnahme werfen.
Java Callable
Das Java Callable Interface verwendet Generics, um den Rückgabetyp des Objekts zu definieren. Die Executors-Klasse bietet nützliche Methoden zur Ausführung von Java Callable in einem Thread-Pool. Da Callable-Aufgaben parallel ausgeführt werden, müssen wir auf das zurückgegebene Objekt warten.
Java Future
Aufgaben von Java Callable geben ein java.util.concurrent.Future Objekt zurück. Mit dem Java Future Objekt können wir den Status der Callable-Aufgabe ermitteln und das zurückgegebene Objekt erhalten. Es bietet eine get()-Methode, die darauf warten kann, dass das Callable fertig wird und dann das Ergebnis zurückgibt. Java Future bietet eine cancel()-Methode, um die zugehörige Callable-Aufgabe abzubrechen. Es gibt eine überladene Version der get()-Methode, bei der wir die Wartezeit auf das Ergebnis angeben können, was nützlich ist, um zu vermeiden, dass der aktuelle Thread für längere Zeit blockiert wird. Es gibt isDone()- und isCancelled()-Methoden, um den aktuellen Status der zugehörigen Callable-Aufgabe herauszufinden. Hier ist ein einfaches Beispiel für eine Java Callable-Aufgabe, die den Namen des Threads zurückgibt, der die Aufgabe nach einer Sekunde ausführt. Wir verwenden das Executor-Framework, um 100 Aufgaben parallel auszuführen und das Java Future, um das Ergebnis der eingereichten Aufgaben zu erhalten.
package com.journaldev.threads;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(1000);
return Thread.currentThread().getName();
}
public static void main(String args[]){
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<String>> list = new ArrayList<Future<String>>();
Callable<String> callable = new MyCallable();
for(int i=0; i< 100; i++){
Future<String> future = executor.submit(callable);
list.add(future);
}
for(Future<String> fut : list){
try {
System.out.println(new Date()+ "::"+fut.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
}
Sobald wir das obige Programm ausführen, werden Sie die Verzögerung im Output bemerken, weil die Java Future get()-Methode darauf wartet, dass die Java Callable-Aufgabe abgeschlossen wird. Beachten Sie auch, dass nur 10 Threads diese Aufgaben ausführen. Hier ist ein Ausschnitt des Outputs des oben genannten Programms.
Mon Dec 31 20:40:15 PST 2012::pool-1-thread-1
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-2
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-3
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-4
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-5
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-6
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-7
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-8
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-9
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-10
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-2
...
Tipp: Was, wenn wir einige Methoden der Java Future Schnittstelle überschreiben möchten, zum Beispiel die get()-Methode so ändern, dass sie nach einer bestimmten Standardzeit abläuft, anstatt unendlich zu warten? In diesem Fall ist die Java FutureTask-Klasse nützlich, die die Basisimplementierung der Future-Schnittstelle ist.