Ce face CompletableFuture.thenCombine
a.thenCombine(b, (x, y) -> ...) așteaptă ca a și b să se termine, apoi apelează funcția cu cele două rezultate. Cele două sarcini rulează în paralel, deci timpul total este cel al sarcinii mai lente, nu suma lor.
Dacă oricare dintre cele două eșuează, rezultatul combinat eșuează și el, iar funcția nu mai este apelată. Pentru mai mult de două sarcini folosește CompletableFuture.allOf.
Parametri
| Parametru | Descriere |
|---|---|
altul |
Al doilea CompletableFuture. |
functie |
Primește cele două rezultate și returnează rezultatul combinat. |
Ce returnează
Un nou CompletableFuture<V> cu rezultatul funcției.
Exemple
Exemplul 1: Prețul în euro: produs și curs, cerute în paralel
Cele două cereri durează câte 300 ms și rulează în același timp; thenCombine le folosește pe amândouă când sunt gata.
import java.util.concurrent.CompletableFuture;
public class Main {
static <T> T dupa(int ms, T valoare) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return valoare;
}
public static void main(String[] args) {
CompletableFuture<Double> pretLei = CompletableFuture.supplyAsync(() -> dupa(300, 2499.0));
CompletableFuture<Double> cursEuro = CompletableFuture.supplyAsync(() -> dupa(300, 4.97));
String text = pretLei
.thenCombine(cursEuro, (lei, curs) -> String.format("Laptop: %.2f lei = %.2f euro", lei, lei / curs))
.join();
System.out.println(text);
}
}
Rezultat
Laptop: 2499.00 lei = 502.82 euro
Exemplul 2: Nume și notă, apoi un mesaj
import java.util.concurrent.CompletableFuture;
public class Main {
public static void main(String[] args) {
CompletableFuture<String> nume = CompletableFuture.supplyAsync(() -> "Ioana");
CompletableFuture<Integer> nota = CompletableFuture.supplyAsync(() -> 10);
nume.thenCombine(nota, (n, x) -> n + " a luat nota " + x + " la matematică")
.thenAccept(System.out::println)
.join();
}
}
Rezultat
Ioana a luat nota 10 la matematică
Exemplul 3: Dacă una eșuează, combinarea eșuează
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
public class Main {
public static void main(String[] args) {
CompletableFuture<Integer> a = CompletableFuture.supplyAsync(() -> 100);
CompletableFuture<Integer> b = CompletableFuture.supplyAsync(() -> Integer.parseInt("x"));
try {
a.thenCombine(b, Integer::sum).join();
} catch (CompletionException e) {
System.out.println("Combinarea a eșuat: " + e.getCause().getClass().getSimpleName());
}
}
}
Rezultat
Combinarea a eșuat: NumberFormatException
Greșeli frecvente
- Faci
a.join()și abia apoi porneștib. Sarcinile rulează una după alta; pornește-le pe amândouă, apoi combină-le. - Folosești
thenCombinecând a doua sarcină are nevoie de rezultatul primei. Atunci foloseștethenCompose.
Comenzi înrudite
CompletableFuture.allOf: Returnează un CompletableFuture care se termină când s-au terminat toate cele primite; anyOf, când s-a terminat primul.CompletableFuture.thenApply: thenApply transformă rezultatul când este gata (ca map); thenAccept îl folosește fără să returneze ceva (ca forEach).CompletableFuture.supplyAsync: Pornește o sarcină pe alt fir și returnează imediat un CompletableFuture; supplyAsync are rezultat, runAsync nu.CompletableFuture: Un Future care se poate înlănțui: definești ce se întâmplă cu rezultatul (thenApply, thenAccept) fără să aștepți; join() îl ia la final.