Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lernen CompletableFuture | Best Practices für Multithreading
Multithreading in Java
course content

Kursinhalt

Multithreading in Java

Multithreading in Java

1. Grundlagen der Multithread-Verarbeitung
2. Synchronisierte Sammlungen
3. Hochrangige Synchronisationsmechanismen
4. Best Practices für Multithreading

book
CompletableFuture

Es gibt noch einen letzten Sprung! In diesem Kapitel werden wir uns die Hauptklasse für Asynchronität CompletableFuture ansehen.

Lassen Sie uns eine realistische Analogie verwenden. Sie rufen ein Taxi über eine App (Aufgabenerstellung). Während Sie warten, kann die App Updates über den Standort des Autos oder die geschätzte Ankunftszeit bereitstellen (Ergebnisverarbeitung). Wenn es Probleme wie Verzögerungen oder Stornierungen gibt, wird die App Sie benachrichtigen und Alternativen vorschlagen (Fehlerbehandlung).

Hauptmethoden

Die erste Frage, die Sie sich stellen könnten, ist, wie man eine Aufgabe starten kann, indem man CompletableFuture verwendet. Dazu können Sie die supplyAsync() Methode verwenden, die dazu entwickelt wurde, eine Aufgabe auszuführen, die das Ergebnis asynchron zurückgibt.

java

Main

copy
12345678910
// Creating an asynchronous task CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { return "Result"; // Result }); // Processing the result after the task completes future.thenAccept(result -> { // Print the result to the console System.out.println("Result received: " + result); // Result received: });

Wir haben auch die thenAccept() Methode, die den Wert verarbeitet, der von CompletableFuture in asynchronem Code zurückgegeben wird. Sie gibt nichts zurück; sie ist nützlich, wenn Sie eine Antwort akzeptieren und auf irgendeine Weise verarbeiten müssen.

Hinweis

In unserem Beispiel führen wir die Aufgabe asynchron aus, und future.thenAccept() erhält die Antwort von der Lambda, die wir dann verwenden können, um sie auf der Konsole auszudrucken.

Es gibt eine ähnliche Methode, thenApply(), die wie thenAccept() funktioniert, aber das Ergebnis der asynchronen Aufgabe erhält und ein neues Ergebnis zurückgibt.

java

Main

copy
12345678910
// Creating an asynchronous task that returns "Hello, World!" CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello, World!"); // Transforming the result to uppercase CompletableFuture<String> transformedFuture = future.thenApply(result -> result.toUpperCase()); // Printing the transformed result to the console transformedFuture.thenAccept(result -> { System.out.println("Transformed result: " + result); // Transformed result: });

Was ist, wenn wir das Ergebnis der asynchronen Aufgabe nicht erhalten möchten, sondern einfach nur benachrichtigt werden wollen, wenn sie abgeschlossen ist?

Dafür können wir thenRun() verwenden, das ausgeführt wird, nachdem die asynchrone Aufgabe abgeschlossen ist.

java

Main

copy
12345678
// Creating an asynchronous task that returns "Hello, World!" CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello, World!"); // Running a task when the previous task completes future.thenRun(() -> { // Print message to the console indicating that the task is complete System.out.println("Task completed!"); // Task completed! });

Wir können das Ergebnis einer asynchronen Aufgabe auch abrufen, indem wir den aktuellen Thread blockieren, bis die Aufgabe abgeschlossen ist. Zu diesem Zweck verwenden wir die get() Methode.

java

Main

copy
1234567
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello World"); try { String result = completableFuture.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); }

Es gibt auch eine Methode join(), die ebenfalls den aktuellen Thread pausiert und auf die asynchrone Aufgabe wartet, um abgeschlossen zu werden. Der Unterschied zwischen join() und get() besteht jedoch darin, dass sie unterschiedliche Ausnahmen werfen.

java

Main

copy
12345
// Create a `CompletableFuture` that asynchronously executes a task and returns the string "Hello World". CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello World"); // The `join()` method blocks the current thread until the task is completed and returns the result "Hello World". String result = completableFuture.join();

Wir behandeln die Ausnahme hier nicht, weil die join()-Methode eine unchecked CompletionException wirft.

Aufgaben kombinieren und verketten

Wir können Aufgaben kombinieren in CompletableFuture mit thenCompose(), das 2 abhängige Aufgaben kombiniert.

java

Main

copy
12345678910111213141516171819202122232425
// Method to get book details from a remote service public CompletableFuture<String> getBookDetails() { return CompletableFuture.supplyAsync(() -> { // Request to a remote service to get book details return "Book Details"; // Placeholder for book details }); } // Method to get author details from a remote service public CompletableFuture<String> getAuthorDetails(String bookDetails) { return CompletableFuture.supplyAsync(() -> { // Request to another service to get author details return bookDetails + " Author"; // Placeholder for author details }); } // Combine two asynchronous tasks: get book details and then get author details CompletableFuture<String> result = getBookDetails() .thenCompose(book -> getAuthorDetails(book)); // Process the result and print the author details to the console result.thenAccept(author -> { // Print the author details to the console System.out.println("Author: " + author); // Author details });

Wir rufen zuerst die Buchdaten asynchron mit der Methode getBookDetails() ab und verwenden dann das Ergebnis, um die nächste asynchrone Aufgabe auszuführen—das Abrufen der Autorendaten über die Methode getAuthorDetails(). Nachdem beide Aufgaben abgeschlossen sind, wird das Ergebnis (Autoreninformationen) auf der Konsole angezeigt.

Wir können auch die Ergebnisse von zwei Aufgaben zusammenführen mit der thenCombine() Methode. Sie führt beide Aufgaben gleichzeitig aus und kombiniert ihre Ergebnisse, sobald beide Aufgaben abgeschlossen sind.

java

Main

copy
123456789101112
// CompletableFuture for adding two numbers CompletableFuture<Double> firstNumberFuture = CompletableFuture.supplyAsync(() -> 50.0); CompletableFuture<Double> secondNumberFuture = CompletableFuture.supplyAsync(() -> 30.0); // Combine the two futures by adding their results CompletableFuture<Double> sumFuture = firstNumberFuture.thenCombine(secondNumberFuture, (first, second) -> first + second); // Print the result of the addition to the console sumFuture.thenAccept(sum -> { System.out.println("Sum: " + sum); // Sum: 80.0 });

Dieser Code ruft zwei Zahlen asynchron ab, summiert sie und gibt das Ergebnis auf der Konsole aus.

Wir können auch warten, bis alle Aufgaben abgeschlossen sind, indem wir die allOf() Methode verwenden, oder auf eine beliebige von ihnen mit der anyOf() Methode.

java

Main

copy
1234567891011121314151617181920
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> { // Task 1 System.out.println("Task 1 completed"); }); CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> { // Task 2 System.out.println("Task 2 completed"); }); // Combine both futures and wait for both tasks to complete CompletableFuture<Void> combinedFuture1 = CompletableFuture.allOf(future1, future2); // Combine both futures and proceed as soon as any one task completes CompletableFuture<Object> combinedFuture2 = CompletableFuture.anyOf(future1, future2); // Print a message after all tasks are completed combinedFuture1.thenRun(() -> { System.out.println("All tasks completed"); });

Wie gehen Sie mit Fehlern um und was ist ein Timeout?

Kurzer Clip aus dem Video

  • handle(): Verarbeitet das Ergebnis oder behandelt alle Ausnahmen, die von der CompletableFuture ausgelöst werden;
  • exceptionally(): Behandelt Ausnahmen, die während der Ausführung der CompletableFuture ausgelöst werden;
  • completeOnTimeout(): Schließt die CompletableFuture mit einem angegebenen Wert ab, wenn sie vor dem Abschluss abläuft.

Zusammenfassung

CompletableFuture erleichtert das Management von asynchronen Aufgaben und die Verarbeitung ihrer Ergebnisse, was es zu einem leistungsstarken Werkzeug für die Entwicklung moderner Anwendungen macht.

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 4. Kapitel 6
We're sorry to hear that something went wrong. What happened?
some-alt