Zusammenfassung der gleichzeitigen Java-Programmierung 11: Future, FutureTask

public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}


public class FutureTask<V> implements RunnableFuture<V> {
 
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        // ...       
    }
 
    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        // ...
    }
}

Aus dem Konstruktor ist ersichtlich, dass FutureTask entweder Callable-Tasks oder Runnable-Tasks umschließen kann, aber am Ende ist es immer die Konvertierung von Runnable in Callable-Tasks, was eigentlich ein Anpassungsprozess ist.

Durch die obige Analyse können wir sehen, dass die gesamte Zukunft tatsächlich aus drei Kernkomponenten besteht:

  1. Echte Aufgabe / Datentyp (normalerweise ist die Ausführung der Aufgabe langsam oder die Datenerstellung dauert lange);
  2. Zukünftige Schnittstelle (der Anrufer verwendet den Berechtigungsnachweis, um das Ergebnis der tatsächlichen Aufgabe / Daten zu erhalten), dh die zukünftige Schnittstelle.
  3. Zukünftige Implementierungsklasse (zum Umschließen realer Aufgaben / Daten), nämlich FutureTask-Implementierungsklasse.

Im von JUC bereitgestellten Future-Modus ist die FutureTask-Klasse die wichtigste. FutureTask wurde mit JUC bei JDK1.5 eingeführt. Sie stellt eine asynchrone Aufgabe dar. Diese Aufgabe wird im Allgemeinen zur Ausführung an Executor gesendet und kann natürlich auch aufgerufen werden Die Partei ruft direkt die Ausführungsmethode auf, um sie auszuführen.

In dem Buch "Die Kunst der gleichzeitigen Programmierung von Java" unterteilt der Autor FutureTask entsprechend dem Zeitpunkt der Ausführung der FutureTask.run () -Methode in drei Zustände:

  1. Nicht gestartet . Bevor die FutureTask.run () -Methode ausgeführt wird, befindet sich die FutureTask in einem nicht gestarteten Zustand . Wenn eine FutureTask erstellt wird, wird die FutureTask nicht gestartet, bevor die FutureTask.run () -Methode ausgeführt wird.
  2. Wurde aktiviert . Während der Ausführung der FutureTask.run () -Methode befindet sich die FutureTask im gestarteten Zustand.
  3. Abgeschlossen . Die Ausführung der FutureTask.run () -Methode wird beendet, oder die FutureTask.cancel (...) -Methode wird aufgerufen, um die Aufgabe abzubrechen, oder während der Ausführung der Aufgabe wird eine Ausnahme ausgelöst. Diese Situationen werden als abgeschlossener Status der FutureTask bezeichnet .

Die folgende Abbildung fasst den Statusänderungsprozess von FutureTask zusammen:

Da FutureTask diese drei Zustände hat, sind die Ergebnisse der Ausführung der get-Methode und der cancel-Methode von FutureTask auch in verschiedenen Zuständen sehr unterschiedlich. Hier ist eine Zusammenfassung der get-Methode und der cancel-Methode:

Methode abrufen:

  • Wenn die FutureTask nicht gestartet oder gestartet wird , wird der aufrufende Thread durch die Ausführung der FutureTask.get () -Methode blockiert .
  • Wenn sich die FutureTask im abgeschlossenen Zustand befindet , führt der Aufruf der FutureTask.get () -Methode dazu, dass der aufrufende Thread das Ergebnis sofort zurückgibt oder eine Ausnahme auslöst .

Abbruchmethode:

  • Wenn FutureTask nicht gestartet wird , führen Sie die FutureTask.cancel () -Methode aus, und diese Aufgabe wird niemals ausgeführt.
  • Wenn FutureTask in gestartet Zustand , Ausführung FutureTask.cancel (true) Methode zur Unterbrechung der Faden Art und Weise um die Aufgabe zu beenden , um fortzufahren, wenn Sie FutureTask.cancel (false) tun wird keine Auswirkungen auf den Thread, der eine Aufgabe ausführt;
  • Wenn sich die FutureTask im abgeschlossenen Zustand befindet , gibt die Ausführung der FutureTask.cancel (...) -Methode false zurück .

Verwenden Sie die folgende Abbildung, um die Methode get () und cancel () von Future zusammenzufassen:

Neben der Future-Schnittstelle implementiert FutureTask auch die Runnable-Schnittstelle.

Daher kann FutureTask zur Ausführung an Executor übergeben oder direkt vom aufrufenden Thread (FutureTask.run ()) ausgeführt werden.

Darüber hinaus kann die Erfassung von FutureTask ein FutureTask-Objekt auch über die ExecutorService.submit () -Methode und anschließend über die FutureTask.get () - oder FutureTask.cancel-Methode zurückgeben.

Anwendungsszenario: Wenn ein Thread warten muss, bis ein anderer Thread eine Aufgabe ausführt, bevor er weiter ausgeführt werden kann, kann FutureTask zu diesem Zeitpunkt verwendet werden. Angenommen, es gibt mehrere Threads, die mehrere Aufgaben ausführen, und jede Aufgabe kann höchstens einmal ausgeführt werden. Wenn mehrere Threads versuchen, dieselbe Aufgabe auszuführen, darf nur ein Thread die Aufgabe ausführen, und andere Threads müssen warten, bis die Aufgabe ausgeführt wird, bevor sie fortfahren.

 

 

Referenz: Sie hören _ Great God, "Die Kunst der gleichzeitigen Programmierung von Java".

 

Ich denke du magst

Origin blog.csdn.net/ScorpC/article/details/113915682
Empfohlen
Rangfolge