Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lære Completablefuture | Beste Praksiser for Multitråding
Multitråding i Java

bookCompletablefuture

Det er ett siste sprang igjen! I dette kapittelet skal vi se på hovedklassen for asynkronitet, CompletableFuture.

La oss bruke en virkelighetsnær analogi. Du bestiller en taxi via en app (oppgaveopprettelse). Mens du venter, kan appen gi oppdateringer om bilens posisjon eller estimert ankomsttid (resultatbehandling). Dersom det oppstår problemer som forsinkelser eller kanselleringer, vil appen varsle deg og foreslå alternativer (unntakshåndtering).

Hovedmetoder

Det første spørsmålet du kanskje stiller er hvordan man starter en oppgave med CompletableFuture. For dette kan du bruke metoden supplyAsync(), som er laget for å utføre en oppgave som returnerer resultatet asynkront.

Main.java

Main.java

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: });

Vi har også thenAccept()-metoden, som håndterer verdien returnert fra CompletableFuture i asynkron kode. Den returnerer ingenting; den er nyttig når du trenger å motta et svar og behandle det på en eller annen måte.

Note
Merk

I vårt eksempel kjører vi oppgaven asynkront, og future.thenAccept() mottar svaret fra lambdaen, som vi deretter kan bruke til å skrive ut til konsollen.

Det finnes en lignende metode, thenApply(), som fungerer som thenAccept(), men henter resultatet av den asynkrone oppgaven og returnerer et nytt resultat.

Main.java

Main.java

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: });

Hva om vi ikke ønsker å hente resultatet av den asynkrone oppgaven, men bare vil bli varslet når den er ferdig?

Til dette kan vi bruke thenRun(), som kjøres etter at den asynkrone oppgaven er fullført.

Main.java

Main.java

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! });

Vi kan også hente resultatet av en asynkron oppgave ved å blokkere den nåværende tråden til oppgaven er fullført. Til dette formålet bruker vi metoden get().

Main.java

Main.java

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

Det finnes også en metode join(), som også pauser den nåværende tråden og venter på at den asynkrone oppgaven skal fullføres. Forskjellen mellom join() og get() er imidlertid at de kaster forskjellige unntak.

Main.java

Main.java

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();

Vi håndterer ikke unntaket her fordi join()-metoden kaster et ukontrollert CompletionException.

Kombinere oppgaver og kjede dem sammen

Vi kan kombinere oppgaver i CompletableFuture ved å bruke thenCompose(), som kombinerer to avhengige oppgaver.

Main.java

Main.java

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 });

Vi henter først bokdata asynkront ved å bruke getBookDetails()-metoden, og bruker deretter resultatet til å utføre neste asynkrone oppgave—å hente forfatterdata gjennom getAuthorDetails()-metoden. Etter at begge oppgavene er fullført, vises resultatet (forfatterinformasjon) i konsollen.

Vi kan også slå sammen resultatene av to oppgaver ved å bruke thenCombine()-metoden. Den kjører begge oppgavene samtidig og kombinerer resultatene når begge oppgavene er fullført.

Main.java

Main.java

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 });

Denne koden henter asynkront to tall, summerer dem og skriver resultatet til konsollen.

Vi kan også vente på at alle oppgaver skal fullføres ved å bruke allOf()-metoden, eller hvilken som helst av dem ved å bruke anyOf()-metoden.

Main.java

Main.java

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"); });

Hvordan håndterer du feil og hva er en timeout?

Kort klipp fra videoen

  • handle(): Behandler resultatet eller håndterer eventuelle unntak kastet av CompletableFuture;
  • exceptionally(): Håndterer unntak som oppstår under utførelsen av CompletableFuture;
  • completeOnTimeout(): Fullfører CompletableFuture med en angitt verdi hvis den ikke fullføres innen tidsfristen.
Note
Merk

CompletableFuture gjør det enkelt å håndtere asynkrone oppgaver og behandle resultatene deres, noe som gjør det til et kraftig verktøy for utvikling av moderne applikasjoner.

Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 4. Kapittel 6

Spør AI

expand

Spør AI

ChatGPT

Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår

Awesome!

Completion rate improved to 3.33

bookCompletablefuture

Sveip for å vise menyen

Det er ett siste sprang igjen! I dette kapittelet skal vi se på hovedklassen for asynkronitet, CompletableFuture.

La oss bruke en virkelighetsnær analogi. Du bestiller en taxi via en app (oppgaveopprettelse). Mens du venter, kan appen gi oppdateringer om bilens posisjon eller estimert ankomsttid (resultatbehandling). Dersom det oppstår problemer som forsinkelser eller kanselleringer, vil appen varsle deg og foreslå alternativer (unntakshåndtering).

Hovedmetoder

Det første spørsmålet du kanskje stiller er hvordan man starter en oppgave med CompletableFuture. For dette kan du bruke metoden supplyAsync(), som er laget for å utføre en oppgave som returnerer resultatet asynkront.

Main.java

Main.java

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: });

Vi har også thenAccept()-metoden, som håndterer verdien returnert fra CompletableFuture i asynkron kode. Den returnerer ingenting; den er nyttig når du trenger å motta et svar og behandle det på en eller annen måte.

Note
Merk

I vårt eksempel kjører vi oppgaven asynkront, og future.thenAccept() mottar svaret fra lambdaen, som vi deretter kan bruke til å skrive ut til konsollen.

Det finnes en lignende metode, thenApply(), som fungerer som thenAccept(), men henter resultatet av den asynkrone oppgaven og returnerer et nytt resultat.

Main.java

Main.java

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: });

Hva om vi ikke ønsker å hente resultatet av den asynkrone oppgaven, men bare vil bli varslet når den er ferdig?

Til dette kan vi bruke thenRun(), som kjøres etter at den asynkrone oppgaven er fullført.

Main.java

Main.java

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! });

Vi kan også hente resultatet av en asynkron oppgave ved å blokkere den nåværende tråden til oppgaven er fullført. Til dette formålet bruker vi metoden get().

Main.java

Main.java

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

Det finnes også en metode join(), som også pauser den nåværende tråden og venter på at den asynkrone oppgaven skal fullføres. Forskjellen mellom join() og get() er imidlertid at de kaster forskjellige unntak.

Main.java

Main.java

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();

Vi håndterer ikke unntaket her fordi join()-metoden kaster et ukontrollert CompletionException.

Kombinere oppgaver og kjede dem sammen

Vi kan kombinere oppgaver i CompletableFuture ved å bruke thenCompose(), som kombinerer to avhengige oppgaver.

Main.java

Main.java

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 });

Vi henter først bokdata asynkront ved å bruke getBookDetails()-metoden, og bruker deretter resultatet til å utføre neste asynkrone oppgave—å hente forfatterdata gjennom getAuthorDetails()-metoden. Etter at begge oppgavene er fullført, vises resultatet (forfatterinformasjon) i konsollen.

Vi kan også slå sammen resultatene av to oppgaver ved å bruke thenCombine()-metoden. Den kjører begge oppgavene samtidig og kombinerer resultatene når begge oppgavene er fullført.

Main.java

Main.java

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 });

Denne koden henter asynkront to tall, summerer dem og skriver resultatet til konsollen.

Vi kan også vente på at alle oppgaver skal fullføres ved å bruke allOf()-metoden, eller hvilken som helst av dem ved å bruke anyOf()-metoden.

Main.java

Main.java

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"); });

Hvordan håndterer du feil og hva er en timeout?

Kort klipp fra videoen

  • handle(): Behandler resultatet eller håndterer eventuelle unntak kastet av CompletableFuture;
  • exceptionally(): Håndterer unntak som oppstår under utførelsen av CompletableFuture;
  • completeOnTimeout(): Fullfører CompletableFuture med en angitt verdi hvis den ikke fullføres innen tidsfristen.
Note
Merk

CompletableFuture gjør det enkelt å håndtere asynkrone oppgaver og behandle resultatene deres, noe som gjør det til et kraftig verktøy for utvikling av moderne applikasjoner.

Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 4. Kapittel 6
some-alt