0Pricing
Java Academy · Lezione

Combinare i future: allOf e anyOf

Attenda tutti i future con allOf e li metta in competizione con anyOf per implementare timeout e logiche di fallback.

Combinare i future: allOf e anyOf è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.

Perché combinare i future?

Quando attività asincrone indipendenti possono essere eseguite in parallelo, è opportuno attendere che siano state completate tutte, oppure la prima, prima di procedere. allOf e anyOf gestiscono entrambi i casi.

allOf: attendere tutti i future

CompletableFuture.allOf(futures...) restituisce un CompletableFuture<Void> che viene completato quando sono stati completati TUTTI i future di input. Se uno fallisce, anche allOf fallisce.

CompletableFuture<String> f1 = fetchUserAsync();
CompletableFuture<List<Order>> f2 = fetchOrdersAsync();
CompletableFuture<Double> f3 = fetchBalanceAsync();
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3);
all.join(); // wait for all three
String user   = f1.join();
List<Order> orders = f2.join();
Double balance = f3.join();

Raccogliere i risultati di allOf

Poiché allOf restituisce Void, raccolga i risultati chiamando join() su ogni singolo future dopo allOf.join().

List<CompletableFuture<String>> futures = List.of(
    fetchAsync("url1"), fetchAsync("url2"), fetchAsync("url3"));
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
    .thenApply(v -> futures.stream()
        .map(CompletableFuture::join)
        .collect(Collectors.toList()))
    .thenAccept(results -> results.forEach(System.out::println))
    .join();

anyOf: vince il primo completato

CompletableFuture.anyOf(futures...) restituisce un CompletableFuture<Object> che viene completato con il risultato del primo future completato, indipendentemente dal tipo.

CompletableFuture<Object> first = CompletableFuture.anyOf(
    fetchFromCacheAsync(),
    fetchFromDbAsync(),
    fetchFromApiAsync()
);
System.out.println("Fastest result: " + first.join());

anyOf come fallback per il timeout

Metta in gara un calcolo reale con un future che rappresenta un timeout. Vince quello che viene completato per primo: in questo modo implementa un pattern di timeout non bloccante.

CompletableFuture<String> real    = fetchDataAsync();
CompletableFuture<String> timeout = CompletableFuture
    .supplyAsync(() -> {
        try { Thread.sleep(2000); } catch (InterruptedException e) {}
        return "timeout-default";
    });
String result = (String) CompletableFuture.anyOf(real, timeout).join();

orTimeout (Java 9+)

orTimeout(time, unit) completa il future con una TimeoutException se non termina in tempo. È più semplice del pattern manuale anyOf-timeout.

CompletableFuture<String> result = fetchDataAsync()
    .orTimeout(3, TimeUnit.SECONDS)
    .exceptionally(ex -> "timeout-default");
System.out.println(result.join());

Chiamate HTTP parallele con allOf

Distribuisca le chiamate a più servizi in parallelo, quindi raccolga i risultati. È molto più veloce delle chiamate sequenziali quando i servizi sono indipendenti.

List<String> urls = List.of(url1, url2, url3);
List<CompletableFuture<String>> futures = urls.stream()
    .map(url -> CompletableFuture.supplyAsync(() -> httpGet(url)))
    .collect(Collectors.toList());
List<String> responses = CompletableFuture
    .allOf(futures.toArray(new CompletableFuture[0]))
    .thenApply(v -> futures.stream().map(CompletableFuture::join).collect(Collectors.toList()))
    .join();

Gestione degli errori in allOf

Se un future in allOf fallisce, anche il future restituito fallisce immediatamente. Racchiuda i singoli future in exceptionally per evitare che un singolo errore comprometta l'intero gruppo.

List<CompletableFuture<String>> safe = futures.stream()
    .map(f -> f.exceptionally(ex -> "ERROR: " + ex.getMessage()))
    .collect(Collectors.toList());
CompletableFuture.allOf(safe.toArray(new CompletableFuture[0])).join();

allOf con tipi diversi

allOf accetta future di tipi diversi. Dopo il join, esegua il cast del risultato di ciascun future al tipo previsto.

CompletableFuture<User> userFuture   = fetchUser(id);
CompletableFuture<Config> configFuture = fetchConfig();
CompletableFuture.allOf(userFuture, configFuture).join();
User   user   = userFuture.join();
Config config = configFuture.join();

Comporre allOf e thenApply

Concateni thenApply a allOf per aggregare i risultati non appena tutti i future vengono completati.

CompletableFuture<String> summary =
    CompletableFuture.allOf(f1, f2, f3)
        .thenApply(v -> "User: " + f1.join() +
                       ", Orders: " + f2.join().size() +
                       ", Balance: " + f3.join());
System.out.println(summary.join());

Considerazioni sui pool di thread

Tutti i future in una chiamata a allOf / anyOf possono essere eseguiti contemporaneamente. Si assicuri che il pool di thread disponga di thread sufficienti oppure utilizzi i virtual thread (Java 21+) per evitare la carenza di risorse.

// With virtual threads (Java 21+):
ExecutorService vt = Executors.newVirtualThreadPerTaskExecutor();
CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> httpGet(url), vt);

Propagazione dell'annullamento

allOf / anyOf non annullano automaticamente i future rimanenti quando uno viene completato o annullato. Se necessario, annulli ciascun future singolarmente.

CompletableFuture<Object> first = CompletableFuture.anyOf(f1, f2, f3);
first.thenRun(() -> Stream.of(f1, f2, f3).forEach(f -> f.cancel(true)));

Verifica rapida

Che cosa restituisce CompletableFuture.anyOf?

Riepilogo

allOf attende tutti i future (fan-in). anyOf utilizza il primo risultato (gara). Utilizzi orTimeout per i timeout. Racchiuda i singoli future in exceptionally per evitare che un singolo errore comprometta l'intero gruppo.

Domande Frequenti

La lezione «Combinare i future: allOf e anyOf» è gratuita?

Sì — il testo completo di «Combinare i future: allOf e anyOf» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.

Cosa imparerò in «Combinare i future: allOf e anyOf»?

Attenda tutti i future con allOf e li metta in competizione con anyOf per implementare timeout e logiche di fallback. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Java Academy?

Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Combinare i future: allOf e anyOf»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Java Academy?

Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Creazione e completamento di CompletableFuture
  2. Concatenare con thenApply e thenCompose
  3. Combinare i future: allOf e anyOf
  4. Gestione degli errori e pipeline HTTP asincrona
← Torna a Java Academy