Ich kann es nicht verstehen, selbst wenn ich das offizielle Dokument von CompletableFuture lese, also verstehe ich das Java-Reverse-Rezept mit einer Hand

Dieser Artikel ist der Artikel von Team Lab Engineering am 9. Tag.

In diesem Artikel werde ich über Completable Future schreiben.

Hintergrund

Ich weiß nicht einmal, ob ich das offizielle Dokument von Completable Future nenne Verstehen Sie das Java-Reverse-Rezept mit einer Hand

Referenz-URL Referenzbuch

CompletableFuture English Version Java11 CompletableFuture japanische Version Java8 [Java Reverse Recipe](https://www.amazon.co.jp/Java%E9%80%86%E5%BC%95%E3%81%8D%E3%83%AC%E3%82%B7 % E3% 83% 94-% E7% AC% AC2% E7% 89% 88-% E7% AB% B9% E6% B7% BB-% E7% 9B% B4% E6% A8% B9 / dp / 4798158445)

Arten der Parallelverarbeitung, Unterschiede

Thread: Die im Thread durchgeführte Verarbeitung kann danach nicht mehr übernommen werden.

future: Aufruf, um den Thread für Methodenblöcke abzurufen

Abschließende Zukunft: Anrufer wird nicht blockiert

Unterschied zwischen dann Übernehmen und dann Akzeptieren

thenApply ・ ・ ・ Das in der Methode verarbeitete Ergebnis kann an die nächste Methode übergeben werden. thenAccept ・ ・ ・ Das in der Methode verarbeitete Ergebnis kann nicht an die nächste Methode übergeben werden.

dann Übernehmen


    CompletableFuture<String> future1 =
        CompletableFuture.supplyAsync(
            () -> {
              //Zeitaufwändiger Prozess
              try {
                Thread.sleep(1000);
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
              return "java1";
            });


//dann Übernehmen
    future1
        .thenApply(
            res -> {
              return res; //res enthält "java1", das in der Rückgabe von future1 definiert ist
            })
        .thenApply(
            res -> {
              return res; //res enthält den Rückgabewert "java1" des ersten dann Apply
            })
        .thenAccept(
            res -> {
              System.out.println(res); //res enthält den zweiten Rückgabewert "java1" von thenApply und wird an die Konsole ausgegeben.
            });

//Konsolenausgabe
// java1

Der Wert von thenApply kann an das nächste thenApply übergeben werden.

dann Akzeptieren


    CompletableFuture<String> future1 =
        CompletableFuture.supplyAsync(
            () -> {
              //Zeitaufwändiger Prozess
              try {
                Thread.sleep(1000);
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
              return "java1";
            });

//dann Akzeptieren
    future1.thenAccept(
        res -> {
          System.out.println(res); // return res;Kann nicht an die nächste Methode übergeben werden
        });

//Konsolenausgabe
// java1

Sie können return nicht in die thenAccept () -Methode schreiben.

Der Grund kann durch erneutes Betrachten des offiziellen Dokuments verstanden werden.

// thenApply
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)

// thenAccept
public CompletableFuture <Void> thenAccept(Consumer<? super T> action)

ThenAccept sagt Void im Rückgabewert, so dass Sie es beim nächsten Mal nicht übergeben können, verstehe ich.

Was ist dann Kombinieren?

Gibt eine neue CompletionStage zurück, die ausgeführt wird, wenn sowohl ** diese Phase ** als auch ** andere angegebene Phasen ** erfolgreich abgeschlossen wurden [Informationen zur Klasse CompletableFuture --then Combine](https://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/CompletableFuture.html#thenCombine-java.util.concurrent.CompletionStage -java.util.function.BiFunction-)

↓ Wenn Sie den obigen Satz so interpretieren, dass Sie ihn verstehen können, ... ** Diese Phase = Zukunft2 ** Wann ** Andere spezifizierte Stufen = Zukunft3 ** Wenn beide von ** Neue auszuführende CompletionStage = (String s1, String s2) -> s1 +" "+ s2 ** Kehrt zurück


    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(
            () -> {
              //Zeitaufwändiger Prozess
              try{
                Thread.sleep(1000);
              } catch (InterruptedException e){
                e.printStackTrace();
              }
              return "java1";
            }
    );

    CompletableFuture<String> future2 = future1.thenApply(
            s -> {
              //Zeitaufwändiger Prozess
              try{
                Thread.sleep(1000);
              } catch (InterruptedException e){
                e.printStackTrace();
              }
              return "java2";
            }
    );

    CompletableFuture<String> future3 = future1.thenApply(
            s -> {
              //Zeitaufwändiger Prozess
              try{
                Thread.sleep(1000);
              } catch (InterruptedException e){
                e.printStackTrace();
              }
              return "java3";
            }
    );

    //In thenCombine, future2 und dem ersten Argument(future3)Wenn beide normal abgeschlossen sind
    // (String s1, String s2) -> s1 + " " +Ausführen von s2
    future2.thenCombine(future3, (String s1, String s2) -> s1 + " " + s2)
            .thenAccept(System.out::println);

//Konsolenausgabe
// java2 java3

Unterschied zwischen thenApply und thenApplyAsync

Einige Methoden, die Rückrufe festlegen, haben "Async" am Ende des Methodennamens. "With Async" Wird im selben Thread wie die vorherige Aufgabe ausgeführt "Kein asynchroner" Thread wird als neue Aufgabe zugewiesen

thenApply ・ ・ ・ Wird in der Reihenfolge future1 → future3 → future2 ausgeführt thenApplyAsync ・ ・ ・ Nach der Ausführung von future4 werden future5 und future6 parallel ausgeführt.

thenApply

Gibt eine neue CompletionStage zurück, die ausgeführt wird, wenn diese Phase erfolgreich abgeschlossen wurde. Das Ergebnis dieser Phase wird als Argument für die angegebene Funktion festgelegt. thenApply

Mit dem Code unten Wird in der Reihenfolge von future1 → future3 → future2 ausgeführt


    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(
            () -> {
              //Zeitaufwändiger Prozess
              try{
                Thread.sleep(1000);
              } catch (InterruptedException e){
                e.printStackTrace();
              }
              return "java1";
            }
    );

    CompletableFuture<String> future2 = future1.thenApply(
            s -> {
              //Zeitaufwändiger Prozess
              try{
                Thread.sleep(1000);
              } catch (InterruptedException e){
                e.printStackTrace();
              }
              return "java2";
            }
    );

    CompletableFuture<String> future3 = future1.thenApply(
            s -> {
              //Zeitaufwändiger Prozess
              try{
                Thread.sleep(1000);
              } catch (InterruptedException e){
                e.printStackTrace();
              }
              return "java3";
            }
    );

    //Wird in der Reihenfolge von future1 → future3 → future2 ausgeführt
    future2.thenCombine(future3, (String s1, String s2) -> s1 + " " + s2)
            .thenAccept(System.out::println);

//Konsolenausgabe
// java2 java3

thenApplyAsync

Wenn diese Phase erfolgreich abgeschlossen wurde, wird das Ergebnis dieser Phase als Argument für die angegebene Funktion festgelegt und eine neue CompletionStage zurückgegeben, die mit der asynchronen Standardausführungsfunktion der Phase ausgeführt wird. thenApplyAsync

Wenn Sie es auf Ihre eigene Weise interpretieren ** Wenn diese Phase (Zukunft 4) ** erfolgreich abgeschlossen wurde Das Ergebnis dieser Phase Zur angegebenen Funktion () ** Auf Argument setzen (s im Lambda-Ausdruck) ** und setzen Verwenden der standardmäßigen asynchronen Ausführungsfunktion dieser Stufe ** Ausgeführt (Inhalt des Lambda-Ausdrucks) ** Gibt eine neue CompletionStage zurück.

Mit dem Code unten Nach der Ausführung von future4 werden future5 und future6 parallel ausgeführt

      CompletableFuture<String> future4 =
              CompletableFuture.supplyAsync(
                      () -> {
                          //Zeitaufwändiger Prozess
                          try {
                              Thread.sleep(1000);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          return "java4";
                      });

      CompletableFuture<String> future5 =
              future4.thenApplyAsync(
                      s -> {
                          //Zeitaufwändiger Prozess
                          try {
                              Thread.sleep(1000);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          return "java5";
                      });

      CompletableFuture<String> future6 =
              future4.thenApplyAsync(
                      s -> {
                          //Zeitaufwändiger Prozess
                          try {
                              Thread.sleep(1000);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          return "java6";
                      });


      //Nach der Ausführung von future4 werden future5 und future6 parallel ausgeführt
      future5
              .thenCombine(future6, (String s1, String s2) -> s1 + " " + s2)
              .thenAccept(System.out::println);

//Konsolenausgabe
// java5 java6

Abschließende zukünftige Fehlerbehandlung

Wenn die asynchrone Verarbeitung (supplyAsync) mit einer Ausnahme fehlschlägt, wird der in der Methode thenApply oder thenAccept angegebene Rückruf nicht aufgerufen. Verwenden Sie in diesem Fall die whenComplete () -Methode oder die exceptionally () -Methode für die Behandlung.

whenComplete

exceptionally

Unterschied zwischen thenCompose und thenApply

Wenn Sie dies lesen, verwenden Sie normalerweise thenApply

thenCompose Gibt eine neue CompletionStage zurück, die ausgeführt wird, wenn diese Phase erfolgreich abgeschlossen wurde, wobei ** diese Phase auf das Argument ** für die angegebene Funktion gesetzt ist.

thenApply Gibt eine neue CompletionStage zurück, die ausgeführt wird, wenn diese Phase erfolgreich abgeschlossen wurde, wobei ** das Ergebnis dieser Phase im Argument ** für die angegebene Funktion festgelegt wird.

public <U> CompletableFuture<U> thenCompose(Function<? super T,? extends CompletionStage<U>> fn)

public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)

Ich kann den Unterschied nicht erkennen, selbst wenn ich das offizielle Dokument lese ...

Ich studiere Completable Future. Verwechselt mit dann Übernehmen und dann Verfassen. Nachtrag: Und ich habe viel von Herrn Uragami gelernt! (∩´∀ `) ∩Warum "Eine der Anwendungen von thenCompose ist, dass ich bereits eine API habe, die eine CompletableFuture zurückgibt, und ich dachte, es wäre Zeit, sie zu kombinieren."

Bitte beziehen Sie sich auf diesen Artikel ThenCompose, wenn Sie bereits eine API haben, die eine CompletableFuture zurückgibt Wenn Sie eine neue erstellen, klicken Sie auf Anwenden Wie Sie sehen können, habe ich ungefähr verstanden, dass die Grundlagen thenApply verwenden sollten.

Zusammenfassung

Ich wusste nicht, wie ich die thenApply-Methode verwenden sollte und wann sie ausgeführt wurde, daher bin ich froh, dass ich diese Gelegenheit genutzt habe, um sie zu kennen.

Recommended Posts

Ich kann es nicht verstehen, selbst wenn ich das offizielle Dokument von CompletableFuture lese, also verstehe ich das Java-Reverse-Rezept mit einer Hand
Ich kann kein Japanisch mit VS-Code (Visual Studio Code) von Ubuntu 18.04.5 eingeben! ?? Wenn Sie VS Code auf Ubuntu herunterladen möchten, besuchen Sie die offizielle Website! !!
Ich habe das Verhalten von Java Scanner und .nextLine () nicht wirklich verstanden.
Seit ich Oracle Java Bronze bestanden habe, habe ich die Umrisse des Tests zusammengefasst.