Completablefuture
Er is nog één laatste sprong te maken! In dit hoofdstuk bekijken we de belangrijkste asynchronieklasse CompletableFuture.
Laten we een realistische analogie gebruiken. Je roept een taxi op via een app (taakcreatie). Terwijl je wacht, kan de app updates geven over de locatie van de auto of de geschatte aankomsttijd (resultaatverwerking). Als er problemen zijn, zoals vertragingen of annuleringen, zal de app je informeren en alternatieven voorstellen (afhandelingsfouten).
Belangrijkste Methoden
De eerste vraag die je misschien stelt is hoe je een taak start met CompletableFuture. Hiervoor kun je de methode supplyAsync() gebruiken, die is ontworpen om een taak uit te voeren die het resultaat asynchroon retourneert.
Main.java
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: });
We beschikken ook over de methode thenAccept(), die de waarde verwerkt die wordt geretourneerd door CompletableFuture in asynchrone code. Deze methode retourneert niets; het is nuttig wanneer een antwoord geaccepteerd en op een bepaalde manier verwerkt moet worden.
In ons voorbeeld voeren we de taak asynchroon uit, en future.thenAccept() ontvangt het antwoord van de lambda, dat vervolgens kan worden gebruikt om naar de console te printen.
Er is een vergelijkbare methode, thenApply(), die werkt zoals thenAccept(), maar ontvangt het resultaat van de asynchrone taak en geeft een nieuw resultaat terug.
Main.java
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: });
Wat als we het resultaat van de asynchrone taak niet willen ontvangen, maar gewoon geïnformeerd willen worden wanneer deze is voltooid?
Hiervoor kunnen we thenRun() gebruiken, die wordt uitgevoerd nadat de asynchrone taak is afgerond.
Main.java
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! });
Het is ook mogelijk het resultaat van een asynchrone taak op te halen door de huidige thread te blokkeren totdat de taak is voltooid. Hiervoor wordt de methode get() gebruikt.
Main.java
1234567CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello World"); try { String result = completableFuture.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); }
Er is ook een methode join(), die eveneens de huidige thread pauzeert en wacht tot de asynchrone taak is voltooid. Het verschil tussen join() en get() is echter dat ze verschillende uitzonderingen genereren.
Main.java
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();
De uitzondering wordt hier niet afgehandeld omdat de methode join() een ongecontroleerde CompletionException genereert.
Taken combineren en aan elkaar koppelen
Taken kunnen worden gecombineerd in CompletableFuture met behulp van thenCompose(), waarmee twee afhankelijke taken worden gecombineerd.
Main.java
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 });
Eerst worden de boekgegevens asynchroon opgehaald met de methode getBookDetails(), waarna het resultaat wordt gebruikt om de volgende asynchrone taak uit te voeren—het ophalen van de auteursgegevens via de methode getAuthorDetails(). Nadat beide taken zijn voltooid, wordt het resultaat (auteursinformatie) weergegeven op de console.
We kunnen ook de resultaten samenvoegen van twee taken met behulp van de methode thenCombine(). Deze voert beide taken gelijktijdig uit en combineert hun resultaten zodra beide taken voltooid zijn.
Main.java
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 });
Deze code haalt asynchroon twee getallen op, telt ze bij elkaar op en drukt het resultaat af naar de console.
We kunnen ook wachten tot alle taken voltooid zijn met de methode allOf(), of op een willekeurige taak met de methode anyOf().
Main.java
1234567891011121314151617181920CompletableFuture<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"); });
Hoe worden fouten afgehandeld en wat is een timeout?
Korte clip uit de video
handle(): Verwerkt het resultaat of behandelt eventuele exceptions die door deCompletableFutureworden opgegooid;exceptionally(): Behandelt exceptions die optreden tijdens de uitvoering van deCompletableFuture;completeOnTimeout(): Rondt deCompletableFutureaf met een opgegeven waarde als deze niet op tijd voltooid is.
CompletableFuture maakt het eenvoudig om asynchrone taken te beheren en hun resultaten te verwerken, waardoor het een krachtig hulpmiddel is voor het ontwikkelen van moderne applicaties.
Bedankt voor je feedback!
Vraag AI
Vraag AI
Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.
What are some practical examples of using CompletableFuture in real applications?
Can you explain the difference between thenAccept(), thenApply(), and thenRun()?
How do you handle exceptions when working with CompletableFuture?
Awesome!
Completion rate improved to 3.33
Completablefuture
Veeg om het menu te tonen
Er is nog één laatste sprong te maken! In dit hoofdstuk bekijken we de belangrijkste asynchronieklasse CompletableFuture.
Laten we een realistische analogie gebruiken. Je roept een taxi op via een app (taakcreatie). Terwijl je wacht, kan de app updates geven over de locatie van de auto of de geschatte aankomsttijd (resultaatverwerking). Als er problemen zijn, zoals vertragingen of annuleringen, zal de app je informeren en alternatieven voorstellen (afhandelingsfouten).
Belangrijkste Methoden
De eerste vraag die je misschien stelt is hoe je een taak start met CompletableFuture. Hiervoor kun je de methode supplyAsync() gebruiken, die is ontworpen om een taak uit te voeren die het resultaat asynchroon retourneert.
Main.java
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: });
We beschikken ook over de methode thenAccept(), die de waarde verwerkt die wordt geretourneerd door CompletableFuture in asynchrone code. Deze methode retourneert niets; het is nuttig wanneer een antwoord geaccepteerd en op een bepaalde manier verwerkt moet worden.
In ons voorbeeld voeren we de taak asynchroon uit, en future.thenAccept() ontvangt het antwoord van de lambda, dat vervolgens kan worden gebruikt om naar de console te printen.
Er is een vergelijkbare methode, thenApply(), die werkt zoals thenAccept(), maar ontvangt het resultaat van de asynchrone taak en geeft een nieuw resultaat terug.
Main.java
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: });
Wat als we het resultaat van de asynchrone taak niet willen ontvangen, maar gewoon geïnformeerd willen worden wanneer deze is voltooid?
Hiervoor kunnen we thenRun() gebruiken, die wordt uitgevoerd nadat de asynchrone taak is afgerond.
Main.java
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! });
Het is ook mogelijk het resultaat van een asynchrone taak op te halen door de huidige thread te blokkeren totdat de taak is voltooid. Hiervoor wordt de methode get() gebruikt.
Main.java
1234567CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello World"); try { String result = completableFuture.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); }
Er is ook een methode join(), die eveneens de huidige thread pauzeert en wacht tot de asynchrone taak is voltooid. Het verschil tussen join() en get() is echter dat ze verschillende uitzonderingen genereren.
Main.java
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();
De uitzondering wordt hier niet afgehandeld omdat de methode join() een ongecontroleerde CompletionException genereert.
Taken combineren en aan elkaar koppelen
Taken kunnen worden gecombineerd in CompletableFuture met behulp van thenCompose(), waarmee twee afhankelijke taken worden gecombineerd.
Main.java
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 });
Eerst worden de boekgegevens asynchroon opgehaald met de methode getBookDetails(), waarna het resultaat wordt gebruikt om de volgende asynchrone taak uit te voeren—het ophalen van de auteursgegevens via de methode getAuthorDetails(). Nadat beide taken zijn voltooid, wordt het resultaat (auteursinformatie) weergegeven op de console.
We kunnen ook de resultaten samenvoegen van twee taken met behulp van de methode thenCombine(). Deze voert beide taken gelijktijdig uit en combineert hun resultaten zodra beide taken voltooid zijn.
Main.java
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 });
Deze code haalt asynchroon twee getallen op, telt ze bij elkaar op en drukt het resultaat af naar de console.
We kunnen ook wachten tot alle taken voltooid zijn met de methode allOf(), of op een willekeurige taak met de methode anyOf().
Main.java
1234567891011121314151617181920CompletableFuture<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"); });
Hoe worden fouten afgehandeld en wat is een timeout?
Korte clip uit de video
handle(): Verwerkt het resultaat of behandelt eventuele exceptions die door deCompletableFutureworden opgegooid;exceptionally(): Behandelt exceptions die optreden tijdens de uitvoering van deCompletableFuture;completeOnTimeout(): Rondt deCompletableFutureaf met een opgegeven waarde als deze niet op tijd voltooid is.
CompletableFuture maakt het eenvoudig om asynchrone taken te beheren en hun resultaten te verwerken, waardoor het een krachtig hulpmiddel is voor het ontwikkelen van moderne applicaties.
Bedankt voor je feedback!