Java-Äquivalent von C # async / warte?

150

Ich bin ein normaler C # -Entwickler, entwickle aber gelegentlich Anwendungen in Java. Ich frage mich, ob es ein Java-Äquivalent von C # async / await gibt. In einfachen Worten, was ist das Java-Äquivalent von:

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();
    var urlContents = await client.GetStringAsync("http://msdn.microsoft.com");
    return urlContents.Length;
}
user960567
quelle
7
Warum das so schön wäre: Rückrufe als Go To Statement unserer Generationen von Miguel de Icaza.
Andrewdotn
Die aktuelle Lösung von Java besteht darin, sich nicht mit tatsächlichen Werten zu befassen, denen ein Präfix vorangestellt ist async, sondern stattdessen Futureoder ObservableWerte zu verwenden.
SD
1
Es gibt kein Äquivalent. Und es tut weh. Eine weitere fehlende Funktion, für die Sie komplizierte Problemumgehungen und Bibliotheken benötigen, ohne jemals den gleichen Effekt wie diese beiden einfachen Wörter zu erzielen.
Spyro
Es ist erwähnenswert, dass Java-Designer seit langem versucht haben, den Java-Bytecode abwärtskompatibel zu halten, wobei nur Änderungen an Bibliotheken und Syntatic-Sugar in Bezug auf vorhandene Funktionen vorgenommen wurden. Beachten Sie die Tatsache, dass Generika keine Laufzeitinformationen speichern und Lambder als Objekt implementiert werden, das eine Schnittstelle implementiert . async / await würde sehr große Änderungen am Bytecode erfordern, um möglich zu sein, und daher würde ich nicht erwarten, ihn bald in Java zu sehen.
Philip Couling

Antworten:

139

Nein, in Java gibt es kein Äquivalent zu async / await - oder sogar in C # vor v5.

Es ist eine ziemlich komplexe Sprachfunktion, eine Zustandsmaschine hinter den Kulissen zu erstellen.

Es gibt relativ wenig Sprachunterstützung für Asynchronität / Parallelität in Java, aber das java.util.concurrentPaket enthält viele nützliche Klassen . (Nicht ganz gleichwertig mit der Task Parallel Library, aber der nächsten Annäherung.)

Jon Skeet
quelle
15
@ user960567: Nein, mein Punkt ist , dass es eine ist die Sprache - Funktion - es kann nicht nur in Bibliotheken gestellt werden. Ich glaube nicht, dass zumindest für Java 8 ein Äquivalent geplant ist.
Jon Skeet
10
@ user960567: Sie müssen zwischen der von Ihnen verwendeten C # -Version und der von Ihnen verwendeten .NET-Version unterscheiden. async / await ist eine Sprache - Funktion - es wurde in C # eingeführt 5. Ja, Sie Microsoft.Bcl.Async verwenden können async / await .NET 4, aber Sie haben noch bekam Targeting einen C # 5 Compiler zu verwenden.
Jon Skeet
5
@rozar: Nein, nicht wirklich. Es gibt bereits mehrere Optionen für die Asynchronität - aber RxJava ändert die Sprache nicht so wie C #. Ich habe nichts gegen Rx, aber es ist nicht dasselbe wie asynchron in C # 5.
Jon Skeet
11
@DtechNet: Nun, es gibt eine Menge JVM-Maschinen, die asynchron sind, ja ... das unterscheidet sich sehr von den tatsächlichen Sprachfunktionen, die Asynchronität unterstützen. (Es gab viel Asynchronität in .NET vor async / await auch ... aber async / await macht es viel einfacher, dies auszunutzen.)
Jon Skeet
1
@Aarkon: Ich würde argumentieren, dass die Antwort immer noch richtig ist , wenn es keine explizite Sprachunterstützung gibt . Es geht nicht nur um Bibliotheken, die die Planung vereinfachen - hier ist es wichtig, wie der C # -Compiler eine Zustandsmaschine erstellt.
Jon Skeet
41

Der awaitverwendet eine Fortsetzung, um zusätzlichen Code auszuführen, wenn die asynchrone Operation abgeschlossen ist ( client.GetStringAsync(...)).

Als engste Annäherung würde ich eine CompletableFuture<T>(Java 8-Äquivalent zu .net Task<TResult>) -basierte Lösung verwenden, um die HTTP-Anforderung asynchron zu verarbeiten.

AKTUALISIERT am 25-05-2016 auf AsyncHttpClient v.2, veröffentlicht am 13. April 2016:

Das Java 8-Äquivalent zum OP-Beispiel AccessTheWebAsync()lautet also wie folgt:

CompletableFuture<Integer> AccessTheWebAsync()
{
    AsyncHttpClient asyncHttpClient = new DefaultAsyncHttpClient();
    return asyncHttpClient
       .prepareGet("http://msdn.microsoft.com")
       .execute()
       .toCompletableFuture()
       .thenApply(Response::getResponseBody)
       .thenApply(String::length);
}

Diese Verwendung wurde aus der Antwort auf Wie erhalte ich eine CompletableFuture von einer Async Http Client-Anfrage? und das entspricht der neuen API in Version 2 von AsyncHttpClient bereitgestellt wird und am 13. April 2016 veröffentlicht wurde und die bereits intrinsische Unterstützung für hat CompletableFuture<T>.

Ursprüngliche Antwort mit Version 1 von AsyncHttpClient:

Zu diesem Zweck haben wir zwei mögliche Ansätze:

  • Der erste verwendet nicht blockierende E / A und ich nenne es AccessTheWebAsyncNio. Da AsyncCompletionHandleres sich jedoch um eine abstrakte Klasse handelt (anstelle einer funktionalen Schnittstelle), können wir kein Lambda als Argument übergeben. Aufgrund der Syntax anonymer Klassen kommt es daher zu unvermeidlicher Ausführlichkeit. Diese Lösung kommt jedoch dem Ausführungsfluss des angegebenen C # -Beispiels am nächsten .

  • Die zweite ist etwas weniger ausführlich, sendet jedoch eine neue Aufgabe , die letztendlich einen Thread blockiert, f.get()bis die Antwort abgeschlossen ist.

Erster Ansatz , ausführlicher, aber nicht blockierend:

static CompletableFuture<Integer> AccessTheWebAsyncNio(){
    final AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
    final CompletableFuture<Integer> promise = new CompletableFuture<>();
    asyncHttpClient
        .prepareGet("https://msdn.microsoft.com")
        .execute(new AsyncCompletionHandler<Response>(){
            @Override
            public Response onCompleted(Response resp) throws Exception {
                promise.complete(resp.getResponseBody().length());
                return resp;
            }
        });
    return promise;
}

Zweiter Ansatz weniger ausführlich, aber Blockieren eines Threads:

static CompletableFuture<Integer> AccessTheWebAsync(){
    try(AsyncHttpClient asyncHttpClient = new AsyncHttpClient()){
        Future<Response> f = asyncHttpClient
            .prepareGet("https://msdn.microsoft.com")
            .execute();
        return CompletableFuture.supplyAsync(
            () -> return f.join().getResponseBody().length());
    }
}
Miguel Gamboa
quelle
1
Eigentlich ist das das Äquivalent zum Happy Flow. Es werden keine Ausnahmen behandelt, schließlich und andere. Durch das Einbeziehen wird der Code viel komplexer und fehleranfälliger.
haimb
1
Dies ist keine Fortsetzung. In diesem Beispiel wird der eigentliche Zweck von async / await übersehen, nämlich den aktuellen Thread freizugeben, um andere Dinge auszuführen, und dann die Ausführung dieser Methode für den aktuellen Thread fortzusetzen, nachdem eine Antwort eingegangen ist. (Dies ist entweder erforderlich, damit der UI-Thread reagiert, oder um die Speichernutzung zu reduzieren.) In diesem Beispiel handelt es sich um eine einfache blockierende Thread-Synchronisierung sowie einige Rückrufe.
Aleksandr Dubinsky
1
@AleksandrDubinsky Ich stimme Ihnen zu, wenn Sie darauf hinweisen, dass der Rückruf möglicherweise nicht im Aufrufer-Thread ausgeführt wird. Du hast recht. Ich bin nicht einverstanden, einen Thread zu blockieren. Meine aktualisierte Antwort von UPDATED am 25-05-2016 ist nicht blockierend.
Miguel Gamboa
1
.... und dieses Beispiel ist genau der Grund, warum C # bei asynchronen Aufgaben so viel einfacher zu schreiben und zu lesen ist. Es ist nur ein Schmerz in Java.
Spyro
29

Schauen Sie sich ea-async an, bei dem Java-Bytecode neu geschrieben wird, um async / wait ziemlich gut zu simulieren. In ihrer Readme-Datei heißt es: "Es ist stark von Async-Await in der .NET CLR inspiriert."

Hafthor
quelle
8
Verwendet es jemand in der Produktion?
Mr. Wang von Next Door
1
Es scheint, dass EA dies tut. Ich glaube nicht, dass sie Geld für etwas ausgeben würden, das nicht für die Produktion geeignet ist.
BrunoJCM
1
Es ist ziemlich normal, Geld für etwas auszugeben und dann zu entscheiden, dass es nicht für die Produktion geeignet ist. Nur so kann man lernen. Es ist möglich, es ohne Java-Agent-Einstellungen in der Produktion zu verwenden. das sollte die Messlatte ein wenig senken ( github.com/electronicarts/ea-async ).
Thoredge
16

asynchron und warten sind syntaktische Zucker. Die Essenz von Async und Warten ist die Zustandsmaschine. Der Compiler wandelt Ihren asynchronen / erwarteten Code in eine Zustandsmaschine um.

Gleichzeitig müssen viele Funktionen der Async-E / A-Bibliothek bereits vorhanden sein, damit Async / Warten in realen Projekten wirklich praktikabel ist . Für C # haben die meisten ursprünglichen synchronisierten E / A-Funktionen eine alternative Async-Version. Der Grund, warum wir diese Async-Funktionen benötigen, ist, dass in den meisten Fällen Ihr eigener Async / Wait-Code auf eine Async-Methode der Bibliothek hinausläuft.

Die Funktionen der Async-Versionsbibliothek in C # ähneln dem AsynchronousChannel-Konzept in Java. Zum Beispiel haben wir AsynchronousFileChannel.read, das entweder eine Zukunft zurückgeben oder einen Rückruf ausführen kann, nachdem der Lesevorgang abgeschlossen ist. Aber es ist nicht genau das gleiche. Alle C # Async-Funktionen geben Aufgaben zurück (ähnlich wie Future, aber leistungsfähiger als Future).

Nehmen wir also an, Java unterstützt async / await und wir schreiben folgenden Code:

public static async Future<Byte> readFirstByteAsync(String filePath) {
    Path path = Paths.get(filePath);
    AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);

    ByteBuffer buffer = ByteBuffer.allocate(100_000);
    await channel.read(buffer, 0, buffer, this);
    return buffer.get(0);
}

Dann würde ich mir vorstellen, dass der Compiler den ursprünglichen asynchronen / wartenden Code in so etwas umwandelt:

public static Future<Byte> readFirstByteAsync(String filePath) {

    CompletableFuture<Byte> result = new CompletableFuture<Byte>();

    AsyncHandler ah = new AsyncHandler(result, filePath);

    ah.completed(null, null);

    return result;
}

Und hier ist die Implementierung für AsyncHandler:

class AsyncHandler implements CompletionHandler<Integer, ByteBuffer>
{
    CompletableFuture<Byte> future;
    int state;
    String filePath;

    public AsyncHandler(CompletableFuture<Byte> future, String filePath)
    {
        this.future = future;
        this.state = 0;
        this.filePath = filePath;
    }

    @Override
    public void completed(Integer arg0, ByteBuffer arg1) {
        try {
            if (state == 0) {
                state = 1;
                Path path = Paths.get(filePath);
                AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);

                ByteBuffer buffer = ByteBuffer.allocate(100_000);
                channel.read(buffer, 0, buffer, this);
                return;
            } else {
                Byte ret = arg1.get(0);
                future.complete(ret);
            }

        } catch (Exception e) {
            future.completeExceptionally(e);
        }
    }

    @Override
    public void failed(Throwable arg0, ByteBuffer arg1) {
        future.completeExceptionally(arg0);
    }
}
caisx25
quelle
15
Synthetischer Zucker? Haben Sie eine Idee, wie Sie Ausnahmen um Async-Code und Async-Code umschließen können?
Akash Kava
38
Auch Klassen sind syntaktischer Zucker. Der Compiler erstellt alle Bäume und Listen von Funktionszeigern, die Sie normalerweise von Hand schreiben würden, vollautomatisch. Diese Funktionen / Methoden sind auch syntaktischer Zucker. Sie generieren automatisch alle Gotos, die Sie normalerweise als echter Programmierer von Hand schreiben würden. Assembler ist auch syntaktischer Zucker. Echte Programmierer schreiben Maschinencode manuell und portieren ihn manuell auf alle Zielarchitekturen.
Yeoman
32
Wenn man darüber nachdenkt, sind Computer selbst nur syntaktischer Zucker für l4m3 n00bz. Echte Programmierer löten sie mit winzigen integrierten Schaltkreisen auf eine Holzplatte und verbinden sie mit Golddraht, da Leiterplatten wie Massenproduktion, Schuhe oder Lebensmittel syntaktischer Zucker sind.
Yeoman
14

In Java gibt es auf Sprachebene kein Äquivalent zu C # async / await. Ein Konzept, das als Fibers aka Cooperative Threads aka Lightweight Threads bekannt ist, könnte eine interessante Alternative sein. Sie finden Java-Bibliotheken, die Fasern unterstützen.

Java-Bibliotheken, die Fasern implementieren

Sie können diesen Artikel (von Quasar) lesen, um eine schöne Einführung in Fasern zu erhalten. Es behandelt, was Threads sind, wie Fasern in der JVM implementiert werden können und enthält einen Quasar-spezifischen Code.

FabienB
quelle
10
async / await in C # ist keine Faser. Es ist nur Compiler-Magie, die die Fortsetzung von Promise (der TaskKlasse) verwendet, indem sie einen Rückruf registriert.
UltimaWeapon
1
@UltimaWeapon Was halten Sie für Fasern?
Aleksandr Dubinsky
@AleksandrDubinsky Eines der Beispiele ist Goroutine.
UltimaWeapon
1
@UltimaWeapon Ich habe nach einer Erklärung gesucht.
Aleksandr Dubinsky
@AleksandrDubinsky Ich bin faul, es zu erklären. Wenn Sie es wirklich wissen wollen, können Sie den Artikel unter der Haube von Goroutine durchsuchen.
UltimaWeapon
8

Wie bereits erwähnt, gibt es kein direktes Äquivalent, aber mit Java-Bytecode-Modifikationen könnte eine sehr enge Annäherung erstellt werden (sowohl für asynchrone / warteähnliche Anweisungen als auch für die zugrunde liegende Fortsetzung der Implementierung).

Ich arbeite gerade an einem Projekt, das async / await über der JavaFlow-Fortsetzungsbibliothek implementiert. Überprüfen Sie dies bitte https://github.com/vsilaev/java-async-await

Es wurde noch kein Maven-Mojo erstellt, aber Sie können Beispiele mit dem mitgelieferten Java-Agenten ausführen. So sieht asynchroner / wartender Code aus:

public class AsyncAwaitNioFileChannelDemo {

public static void main(final String[] argv) throws Exception {

    ...
    final AsyncAwaitNioFileChannelDemo demo = new AsyncAwaitNioFileChannelDemo();
    final CompletionStage<String> result = demo.processFile("./.project");
    System.out.println("Returned to caller " + LocalTime.now());
    ...
}


public @async CompletionStage<String> processFile(final String fileName) throws IOException {
    final Path path = Paths.get(new File(fileName).toURI());
    try (
            final AsyncFileChannel file = new AsyncFileChannel(
                path, Collections.singleton(StandardOpenOption.READ), null
            );              
            final FileLock lock = await(file.lockAll(true))
        ) {

        System.out.println("In process, shared lock: " + lock);
        final ByteBuffer buffer = ByteBuffer.allocateDirect((int)file.size());

        await( file.read(buffer, 0L) );
        System.out.println("In process, bytes read: " + buffer);
        buffer.rewind();

        final String result = processBytes(buffer);

        return asyncResult(result);

    } catch (final IOException ex) {
        ex.printStackTrace(System.out);
        throw ex;
    }
}

@async ist die Annotation, die eine Methode als asynchron ausführbare Datei kennzeichnet. await () ist eine Funktion, die auf CompletableFuture mit Fortsetzungen wartet, und ein Aufruf von "asyncResult (someValue) zurückgeben" beendet die zugehörige CompletableFuture / Continuation

Wie bei C # bleibt der Kontrollfluss erhalten und die Ausnahmebehandlung kann regelmäßig erfolgen (try / catch wie bei sequentiell ausgeführtem Code).

Valery Silaev
quelle
6

Java selbst hat keine entsprechenden Funktionen, es gibt jedoch Bibliotheken von Drittanbietern, die ähnliche Funktionen bieten, z . B. Kilim .

Alexei Kaigorodov
quelle
3
Ich glaube nicht, dass diese Bibliothek etwas mit dem zu tun hat, was async / await macht.
Natan
5

Verstehe zuerst, was Async / Warten ist. Auf diese Weise kann eine Single-Threaded-GUI-Anwendung oder ein effizienter Server mehrere "Fasern" oder "Co-Routinen" oder "Lightweight-Threads" auf einem einzelnen Thread ausführen.

Wenn Sie mit der Verwendung gewöhnlicher Threads einverstanden sind, lautet das Java-Äquivalent ExecutorService.submitundFuture.get . Dies wird blockiert, bis die Aufgabe abgeschlossen ist, und das Ergebnis zurückgegeben. In der Zwischenzeit können andere Threads funktionieren.

Wenn Sie den Vorteil von Fasern nutzen möchten, benötigen Sie Unterstützung im Container (ich meine in der GUI-Ereignisschleife oder im Server-HTTP-Anforderungshandler) oder indem Sie Ihren eigenen schreiben.

Servlet 3.0 bietet beispielsweise eine asynchrone Verarbeitung. JavaFX bietet javafx.concurrent.Task. Diese haben jedoch nicht die Eleganz von Sprachmerkmalen. Sie arbeiten mit gewöhnlichen Rückrufen.

Aleksandr Dubinsky
quelle
2
Hier ist ein Artikelzitat, in dem der erste Absatz dieser Antwort neu gestartet wird. // Zitat starten Für Clientanwendungen wie Windows Store, Windows Desktop und Windows Phone-Apps ist der Hauptvorteil von Async die Reaktionsfähigkeit. Diese Arten von Apps verwenden hauptsächlich Async, um die Benutzeroberfläche ansprechbar zu halten. Bei Serveranwendungen ist der Hauptvorteil von Async die Skalierbarkeit. msdn.microsoft.com/en-us/magazine/dn802603.aspx
granadaCoder
3

In Java gibt es nichts Natives, mit dem Sie dies wie asynchrone / wartende Schlüsselwörter tun können. Wenn Sie jedoch wirklich möchten, können Sie einen CountDownLatch verwenden . Du könntest dann asynchron / warten imitieren, indem Sie dies weitergeben (zumindest in Java7). Dies ist eine gängige Praxis beim Testen von Android-Einheiten, bei denen wir einen asynchronen Aufruf tätigen müssen (normalerweise eine von einem Handler gepostete ausführbare Datei) und dann auf das Ergebnis warten müssen (Countdown).

Dies jedoch in Ihrer Anwendung im Gegensatz zu Ihrem Test zu verwenden, ist NICHT das, was ich empfehle. Das wäre extrem schlecht, da CountDownLatch davon abhängt, dass Sie effektiv die richtige Anzahl von Malen und an den richtigen Stellen herunterzählen.

Stevebot
quelle
3

Ich mache und veröffentlichte Java async / await Bibliothek. https://github.com/stofu1234/kamaitachi

Diese Bibliothek benötigt keine Compiler-Erweiterung und realisiert eine stapellose E / A-Verarbeitung in Java.

    async Task<int> AccessTheWebAsync(){ 
        HttpClient client= new HttpClient();
        var urlContents= await client.GetStringAsync("http://msdn.microsoft.com");
       return urlContents.Length;
    }

   ↓

    //LikeWebApplicationTester.java
    BlockingQueue<Integer> AccessTheWebAsync() {
       HttpClient client = new HttpClient();
       return awaiter.await(
            () -> client.GetStringAsync("http://msdn.microsoft.com"),
            urlContents -> {
                return urlContents.length();
            });
    }
    public void doget(){
        BlockingQueue<Integer> lengthQueue=AccessTheWebAsync();
        awaiter.awaitVoid(()->lengthQueue.take(),
            length->{
                System.out.println("Length:"+length);
            }
            );
    }
stofu
quelle
1

Java hat leider kein Äquivalent zu async / await. Das nächste, was Sie erreichen können, ist wahrscheinlich mit ListenableFuture von Guava und Listener-Verkettung, aber es wäre immer noch sehr umständlich, für Fälle mit mehreren asynchronen Aufrufen zu schreiben, da die Verschachtelungsebene sehr schnell zunehmen würde.

Wenn Sie eine andere Sprache als JVM verwenden möchten, gibt es in Scala glücklicherweise Async / Warten, ein direktes C # Async / Warten-Äquivalent mit einer nahezu identischen Syntax und Semantik: https://github.com/scala/ async /

Beachten Sie, dass diese Funktionalität zwar eine ziemlich erweiterte Compiler-Unterstützung in C # benötigt, in Scala jedoch dank eines sehr leistungsfähigen Makrosystems in Scala als Bibliothek hinzugefügt werden kann und daher auch älteren Versionen von Scala wie 2.10 hinzugefügt werden kann. Zusätzlich ist Scala klassenkompatibel mit Java, sodass Sie den asynchronen Code in Scala schreiben und ihn dann von Java aus aufrufen können.

Es gibt auch ein anderes ähnliches Projekt namens Akka Dataflow http://doc.akka.io/docs/akka/2.3-M1/scala/dataflow.html , das unterschiedliche Formulierungen verwendet, aber konzeptionell sehr ähnlich ist, jedoch mit begrenzten Fortsetzungen und nicht mit Makros implementiert wird (So ​​funktioniert es auch mit älteren Scala-Versionen wie 2.9).

Piotr Kołaczkowski
quelle
1

Java hat kein direktes Äquivalent zur C # -Sprachenfunktion namens async / await, es gibt jedoch einen anderen Ansatz für das Problem, das async / await zu lösen versucht. Es heißt Projekt Loom und bietet virtuelle Threads für die Parallelität mit hohem Durchsatz. Es wird in einer zukünftigen Version von OpenJDK verfügbar sein.

Dieser Ansatz löst auch das " Problem der farbigen Funktion ", das Async / Warten hat.

Ähnliches gilt auch für Golang ( Goroutinen ).

Martin Obrátil
quelle
0

Wenn Sie nur nach sauberem Code suchen, der den gleichen Effekt wie async / await in Java simuliert, und es Ihnen nichts ausmacht, den aufgerufenen Thread zu blockieren, bis er abgeschlossen ist, z. B. in einem Test, können Sie Folgendes verwenden:

interface Async {
    void run(Runnable handler);
}

static void await(Async async) throws InterruptedException {

    final CountDownLatch countDownLatch = new CountDownLatch(1);
    async.run(new Runnable() {

        @Override
        public void run() {
            countDownLatch.countDown();
        }
    });
    countDownLatch.await(YOUR_TIMEOUT_VALUE_IN_SECONDS, TimeUnit.SECONDS);
}

    await(new Async() {
        @Override
        public void run(final Runnable handler) {
            yourAsyncMethod(new CompletionHandler() {

                @Override
                public void completion() {
                    handler.run();
                }
            });
        }
    });
Pellet
quelle
0

Die AsynHelper- Java-Bibliothek enthält eine Reihe von Dienstprogrammklassen / -methoden für solche asynchronen Aufrufe (und Wartezeiten).

Wenn eine Reihe von Methodenaufrufen oder Codeblöcken asynchron ausgeführt werden soll, enthält es eine nützliche Hilfsmethode AsyncTask .submitTasks wie im folgenden Snippet.

AsyncTask.submitTasks(
    () -> getMethodParam1(arg1, arg2),
    () -> getMethodParam2(arg2, arg3)
    () -> getMethodParam3(arg3, arg4),
    () -> {
             //Some other code to run asynchronously
          }
    );

Wenn gewartet werden soll, bis alle asynchronen Codes vollständig ausgeführt wurden, kann die Variable AsyncTask.submitTasksAndWait verwendet werden.

Wenn ein Rückgabewert von jedem asynchronen Methodenaufruf oder Codeblock abgerufen werden soll, kann der AsyncSupplier .submitSuppliers verwendet werden, sodass das Ergebnis von dem von der Methode zurückgegebenen Array der Ergebnislieferanten abgerufen werden kann. Unten ist das Beispiel-Snippet:

Supplier<Object>[] resultSuppliers = 
   AsyncSupplier.submitSuppliers(
     () -> getMethodParam1(arg1, arg2),
     () -> getMethodParam2(arg3, arg4),
     () -> getMethodParam3(arg5, arg6)
   );

Object a = resultSuppliers[0].get();
Object b = resultSuppliers[1].get();
Object c = resultSuppliers[2].get();

myBigMethod(a,b,c);

Wenn sich der Rückgabetyp jeder Methode unterscheidet, verwenden Sie die folgende Art von Snippet.

Supplier<String> aResultSupplier = AsyncSupplier.submitSupplier(() -> getMethodParam1(arg1, arg2));
Supplier<Integer> bResultSupplier = AsyncSupplier.submitSupplier(() -> getMethodParam2(arg3, arg4));
Supplier<Object> cResultSupplier = AsyncSupplier.submitSupplier(() -> getMethodParam3(arg5, arg6));

myBigMethod(aResultSupplier.get(), bResultSupplier.get(), cResultSupplier.get());

Das Ergebnis der asynchronen Methodenaufrufe / Codeblöcke kann auch an einem anderen Codepunkt im selben Thread oder an einem anderen Thread wie im folgenden Snippet abgerufen werden.

AsyncSupplier.submitSupplierForSingleAccess(() -> getMethodParam1(arg1, arg2), "a");
AsyncSupplier.submitSupplierForSingleAccess(() -> getMethodParam2(arg3, arg4), "b");
AsyncSupplier.submitSupplierForSingleAccess(() -> getMethodParam3(arg5, arg6), "c");


//Following can be in the same thread or a different thread
Optional<String> aResult = AsyncSupplier.waitAndGetFromSupplier(String.class, "a");
Optional<Integer> bResult = AsyncSupplier.waitAndGetFromSupplier(Integer.class, "b");
Optional<Object> cResult = AsyncSupplier.waitAndGetFromSupplier(Object.class, "c");

 myBigMethod(aResult.get(),bResult.get(),cResult.get());
Loganathan
quelle