Was ist die empfohlene Methode, um zu warten, bis die Completable Future-Threads abgeschlossen sind?

Lesezeit: 3 Minuten

Benutzeravatar von user2121
Benutzer2121

ich benutze CompletableFuture wie unten im Code gezeigt. Aber in Bezug auf die Art und Weise, wie ich warten sollte, bis alle Runnables fertig sind, habe ich zwei Möglichkeiten gefunden, und ich kenne den Unterschied zwischen ihnen nicht und welche ist die beste Methode? Sie sind wie folgt:

Code:

this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedSERun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor);
this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedNWRun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor);
this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedNERun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor);
this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedSWRun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor);

Erster Ansatz, um zu warten, bis alle Runnables fertig sind:

this.growSeedExecutor.shutdown();
this.growSeedExecutor.awaitTermination(1, TimeUnit.DAYS);

Zweiter Ansatz, um zu warten, bis alle Runnables fertig sind:

CompletableFuture.allOf(this.growSeedFutureList).join();

Bitte lassen Sie mich wissen, welches empfohlen wird.

  • Beide würden funktionieren, also hängt es davon ab, was Sie mit dem Executor machen möchten: Wenn Sie ihn nicht mehr brauchen, verwenden Sie den ersteren – wenn Sie ihn wiederverwenden möchten, verwenden Sie den letzteren … Auch in Ihrem ersten Code-Snippet Sie nur Behalten Sie einen Verweis auf die letzte CompletableFuture …

    – Assylias

    8. Juni 2015 um 10:05 Uhr

  • Ich habe nicht ganz verstanden this.growSeedFutureList = . Was ist die Art von growSeedFutureList ? Ist dies eine neue Syntax zum Hinzufügen von Elementen zur Liste? Kann bitte jemand aufklären? Gibt es eine Möglichkeit, dies zu erreichen, ohne eine Liste zu haben?

    – Albatros

    16. September 2021 um 18:35 Uhr

Wenn Sie wirklich auf alle Zukünfte warten wollen, können Sie einfach anrufen join() auf jedem von ihnen:

growSeedFutureList.forEach(CompletableFuture::join);

Der Hauptunterschied im Vergleich zur Verwendung allOf() ist, dass dies eine Ausnahme auslöst, sobald es eine Zukunft erreicht, die mit einer Ausnahme abgeschlossen ist, während die allOf().join() -Version wird nur dann eine Ausnahme auslösen, wenn alle Futures abgeschlossen sind (ausnahmsweise oder nicht).

Ein weiterer kleiner Unterschied besteht darin, dass dies der Vermittler nicht schafft allOf Bühne. Eine solche Phase bleibt nützlich, wenn Sie etwas asynchron tun möchten, nachdem alle Futures abgeschlossen sind, anstatt nur darauf zu warten, dass alle abgeschlossen sind.

Die Lösung mit dem Executor auf der anderen Seite hat mehrere Nachteile:

  • es verhindert, dass der Executor wiederverwendet wird, da er heruntergefahren werden muss;
  • Es erfordert, dass Sie diesen Executor für alle Operationen verwenden – es funktioniert nicht damit CompletableFutures, die auf andere Weise verwaltet werden;
  • es zeigt nicht klar Ihre Absicht, die darin besteht, auf den Abschluss aller Futures zu warten;
  • es ist komplexer zu implementieren;
  • es behandelt keine außergewöhnliche Vervollständigung – es wird keine Ausnahme geworfen awaitTermination() wenn eine der Aufgaben fehlgeschlagen ist.

Beide Wege sind nur gleichwertig, wenn der Executor (growSeedExecutor) ausschließlich für die gegebene Aufgabe verwendet wird. Der erste Weg kann zu folgendem führen: Andere Aufgaben müssen parallelisiert werden, und für jede Aufgabe wird ein neuer Ausführender erstellt. Einige Entwickler sehen, dass zu viele Executoren erstellt wurden, und entscheiden sich für die Verwendung eines einzigen gemeinsamen Executors, konnten jedoch nicht alle Executor-Shutdowns löschen …

Der zweite Weg (join()) ist also zuverlässiger, da er weniger komplex ist. Aber jede neue Zukunft sollte der growSeedFutureList hinzugefügt und nicht zugewiesen werden.

Ein bisschen spät für die Antwort, aber ich hoffe, dieser Code hilft jemandem beim Suchen. Dies verwendet den allgemeinen ForkJoin-Pool-Executor

package com.company;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String args[]){
        List<CompletableFuture> futureList=new ArrayList<>();
        for(int i=0;i<10;i++) {
            futureList.add(CompletableFuture.supplyAsync(()->getThreadName()).thenAccept(name->printThreadName(name)));
        }
        futureList.forEach(CompletableFuture::join);
    }

    static String getThreadName(){
        String threadDetails=Thread.currentThread().getName();
        System.out.println("thread deteails::::"+threadDetails);
        return threadDetails;
    }
    static void printThreadName(String value){
        System.out.println("thread string value::"+value);
    }
}

1431110cookie-checkWas ist die empfohlene Methode, um zu warten, bis die Completable Future-Threads abgeschlossen sind?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy