Java Callable Future Beispiel

Java Callable und Future werden in der Mehrfadenprogrammierung häufig 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 kann, den wir verwenden können. Java 5 hat die java.util.concurrent.Callable-Schnittstelle im Concurrency-Paket eingeführt, die der Runnable-Schnittstelle ähnelt, jedoch ein beliebiges Objekt zurückgeben und eine Ausnahme werfen kann.

Java Callable

Die Java Callable-Schnittstelle verwendet Generics, um den Rückgabetyp des Objekts zu definieren. Die Klasse Executors stellt nützliche Methoden bereit, um Java Callable in einem Thread-Pool auszuführen. Da Callable-Aufgaben parallel ausgeführt werden, müssen wir auf das zurückgegebene Objekt warten.

Java Future

Java Callable-Aufgaben geben ein java.util.concurrent.Future-Objekt zurück. Mit dem Java Future-Objekt können wir den Status der Callable-Aufgabe herausfinden und das zurückgegebene Objekt erhalten. Es stellt die get()-Methode bereit, die darauf warten kann, dass die Callable-Aufgabe beendet wird, und dann das Ergebnis zurückgibt. Java Future bietet die cancel()-Methode zum Abbrechen der zugehörigen Callable-Aufgabe. Es gibt eine überladene Version der get()-Methode, bei der wir die Zeit angeben können, die auf das Ergebnis gewartet werden soll. Dies ist nützlich, um zu verhindern, dass der aktuelle Thread für eine längere Zeit blockiert wird. Die Methoden isDone() und isCancelled() können den aktuellen Status der zugehörigen Callable-Aufgabe ermitteln. 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 verwenden Java Future, um das Ergebnis der übermittelten 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 {

    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        //Geben Sie den Thread-Namen zurück, der diese aufrufbare Aufgabe ausführt
        return Thread.currentThread().getName();
    }
    
    public static void main(String args[]){
        //Holen Sie ExecutorService aus dem Dienstprogramm Executors, die Größe des Thread-Pools beträgt 10
        ExecutorService executor = Executors.newFixedThreadPool(10);
        //Erstellen Sie eine Liste, um das Future-Objekt im Zusammenhang mit Callable zu halten
        List> list = new ArrayList>();
        //Erstellen Sie eine Instanz von MyCallable
        Callable callable = new MyCallable();
        for(int i=0; i< 100; i++){
            //Reichen Sie Callable-Aufgaben ein, die vom Thread-Pool ausgeführt werden sollen
            Future future = executor.submit(callable);
            //Fügen Sie das Future zur Liste hinzu, wir können den Rückgabewert mit Future erhalten
            list.add(future);
        }
        for(Future fut : list){
            try {
                //Geben Sie den Rückgabewert von Future aus, beachten Sie die Verzögerung in der Konsolenausgabe
                //, weil Future.get() auf die Fertigstellung der Aufgabe wartet
                System.out.println(new Date()+ "::"+fut.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        //Schalten Sie den Executor-Service jetzt aus
        executor.shutdown();
    }

}

Nach Ausführung des obigen Programms bemerken Sie die Verzögerung in der Ausgabe, weil die Java Future get() -Methode auf die Fertigstellung der Java-Callable-Aufgabe wartet. Beachten Sie auch, dass nur 10 Threads diese Aufgaben ausführen. Hier ist ein Ausschnitt der Ausgabe des obigen 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
...

Hinweis: Was ist, wenn wir einige Methoden der Java Future-Schnittstelle überschreiben möchten, zum Beispiel die Überschreibung der get()-Methode, um nach einer bestimmten Standardzeit abzulaufen, anstatt unendlich zu warten? In diesem Fall ist die Klasse Java FutureTask nützlich, die die Grundimplementierung der Future-Schnittstelle ist. Schauen Sie sich Java FutureTask Beispiel an, um mehr über diese Klasse zu erfahren.

Source:
https://www.digitalocean.com/community/tutorials/java-callable-future-example