UN CompltableFuture viene utilizzato per la programmazione asincrona. Programmazione asincrona significa scrivere codice non bloccante. Esegue un'attività su un thread separato rispetto al thread principale dell'applicazione e notifica al thread principale il suo avanzamento, completamento o errore.
In questo modo il thread principale non si blocca né attende il completamento dell'attività. Altre attività vengono eseguite in parallelo. Il parallelismo migliora le prestazioni del programma.
Un CompletableFuture è una classe in Java. Appartiene al pacchetto java.util.cocurrent. Implementa l'interfaccia CompletionStage e Future.
Fase di completamento
- Esegue un'azione e restituisce un valore al termine di un'altra fase di completamento.
- Un modello per un'attività che può attivare altre attività.
Quindi, è un elemento di una catena.
Quando più di un thread tenta di completare, completare in via eccezionale o annullare un CompletableFuture, solo uno di essi riesce.
array di byte per stringere java
Futuro vs. CompletabileFuturo
Un CompletableFuture è un'estensione dell'API Future di Java introdotta in Java 8.
Un Future viene utilizzato per la programmazione asincrona. Fornisce due metodi, isDone() e get(). I metodi recuperano il risultato del calcolo una volta completato.
Limitazioni del futuro
- Un futuro non può essere reciprocamente completo.
- Non possiamo eseguire ulteriori azioni sul risultato di un Futuro senza bloccare.
- Il futuro non ha alcuna gestione delle eccezioni.
- Non possiamo combinare più futuri.
Il futuro ha così tante limitazioni, ecco perché abbiamo CompletableFuture. CompletableFuture fornisce un'ampia gamma di metodi per creare più Future, concatenare e combinare. Dispone inoltre di un supporto completo per la gestione delle eccezioni.
Creare un futuro completabile
Possiamo creare un CompletableFuture solo utilizzando il seguente costruttore senza argomenti.
CompletableFuture CompletableFuture = new CompletableFuture();
Esempio
I metodi CompletableFuture più utilizzati sono:
import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; public class CompletableFutureExample1 { public static void main(String[] args) { try { List list = Arrays.asList(5,9,14); list.stream().map(num->CompletableFuture.supplyAsync(()->getNumber(num))).map(CompletableFuture->CompletableFuture.thenApply(n- >n*n)).map(t->t.join()).forEach(s->System.out.println(s)); } catch (Exception e) { e.printStackTrace(); } } private static int getNumber(int a) { return a*a; } }
Produzione:
Gestione delle eccezioni di CompletableFuture
Consideriamo la seguente figura, che rappresenta i cinque CF:
b più albero
Supponiamo che cinque CF in esecuzione e CF21 sollevino un'eccezione, quindi tutti i CF dipendenti (CF31 e CF41) sono in errore. Significa che:
- La chiamata al metodo isCompletedExceptionally() restituisce true.
- La chiamata a get() lancia un'ExecutionException che causa l'eccezione root.
Consideriamo la figura seguente, in cui abbiamo creato CF30 con un'eccezione.
Quando CF21 viene eseguito normalmente, CF30 trasmette semplicemente il valore. Se solleva un'eccezione, CF30 la gestisce e genera valore per CF31.
Esistono tre metodi per gestire un'eccezione:
public CompletableFuture exceptionally(Function function); public CompletableFuture hadle(BiFunction bifunction); public CompletableFuture whenComplete(BiConsumer action);