Ce face CompletableFuture.allOf
allOf(f1, f2, f3) creează un CompletableFuture<Void> care se completează abia după ce s-au completat toate cele primite. Nu adună rezultatele: după allOf(...).join() le iei din fiecare future cu join(), care acum nu mai așteaptă.
Dacă unul dintre ele eșuează, și allOf se termină cu eroare, dar abia după ce s-au terminat toate. anyOf se completează cu rezultatul primului future terminat.
Modelul obișnuit cu o listă: allOf(lista.toArray(new CompletableFuture<?>[0])), apoi lista.stream().map(CompletableFuture::join).toList().
Parametri
| Parametru | Descriere |
|---|---|
toate |
Unul sau mai multe CompletableFuture, sau un tablou de ele. |
Ce returnează
allOf: CompletableFuture<Void>. anyOf: CompletableFuture<Object> cu rezultatul primului terminat.
Exemple
Exemplul 1: Temperaturile din mai multe orașe
Toate cererile pornesc odată. După allOf, rezultatele se citesc în ordinea listei.
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
public class Main {
static final Map<String, Integer> TEMPERATURI = Map.of("Iași", 14, "Cluj", 11, "Constanța", 17, "Brașov", 9);
static int temperatura(String oras) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return TEMPERATURI.get(oras);
}
public static void main(String[] args) {
List<String> orase = List.of("Iași", "Cluj", "Constanța", "Brașov");
List<CompletableFuture<Integer>> cereri = orase.stream()
.map(o -> CompletableFuture.supplyAsync(() -> temperatura(o)))
.toList();
CompletableFuture.allOf(cereri.toArray(new CompletableFuture<?>[0])).join();
List<Integer> valori = cereri.stream().map(CompletableFuture::join).toList();
for (int i = 0; i < orase.size(); i++) {
System.out.println(orase.get(i) + ": " + valori.get(i) + "°C");
}
}
}
Rezultat
Iași: 14°C
Cluj: 11°C
Constanța: 17°C
Brașov: 9°C
Exemplul 2: anyOf: primul răspuns
import java.util.concurrent.CompletableFuture;
public class Main {
static CompletableFuture<String> oglinda(String nume, int ms) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "descărcat de pe " + nume;
});
}
public static void main(String[] args) {
Object primul = CompletableFuture.anyOf(oglinda("ro.mirror", 100), oglinda("de.mirror", 800)).join();
System.out.println(primul);
}
}
Rezultat
descărcat de pe ro.mirror
Exemplul 3: O sarcină eșuată face allOf să eșueze
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
public class Main {
public static void main(String[] args) {
CompletableFuture<Integer> a = CompletableFuture.supplyAsync(() -> 10);
int zero = 0;
CompletableFuture<Integer> b = CompletableFuture.supplyAsync(() -> 10 / zero);
try {
CompletableFuture.allOf(a, b).join();
} catch (CompletionException e) {
System.out.println("allOf a eșuat: " + e.getCause().getMessage());
}
System.out.println("a s-a terminat normal: " + a.join());
}
}
Rezultat
allOf a eșuat: / by zero
a s-a terminat normal: 10
Greșeli frecvente
- Aștepți ca
allOf(...).join()să returneze rezultatele. Returneazănull(tipulVoid); rezultatele le iei din fiecare future. - Scrii
toArray(new CompletableFuture[0]). Este un tip „raw” șijavac -Xlintavertizează; foloseștenew CompletableFuture<?>[0].
Comenzi înrudite
CompletableFuture.thenCombine: Combină rezultatele a două CompletableFuture independente, după ce sunt gata amândouă.CompletableFuture.supplyAsync: Pornește o sarcină pe alt fir și returnează imediat un CompletableFuture; supplyAsync are rezultat, runAsync nu.ExecutorService.invokeAll: Trimite o listă de sarcini și așteaptă să se termine toate; returnează lista de Future în aceeași ordine.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.