Futures
I futures sono stati introdotti in Java 5 (2004). Fondamentalmente sono segnaposto per il risultato di un'operazione che non è ancora terminata. Al termine dell'operazione, Future
conterrà quel risultato. Ad esempio, un'operazione può essere un'istanza Runnable o Callable inviata a ExecutorService . Il mittente dell'operazione può utilizzare l' Future
oggetto per verificare se l'operazione isDone () o attendere che finisca con il metodo get () di blocco .
Esempio:
/**
* A task that sleeps for a second, then returns 1
**/
public static class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Thread.sleep(1000);
return 1;
}
}
public static void main(String[] args) throws Exception{
ExecutorService exec = Executors.newSingleThreadExecutor();
Future<Integer> f = exec.submit(new MyCallable());
System.out.println(f.isDone()); //False
System.out.println(f.get()); //Waits until the task is done, then prints 1
}
CompletableFutures
CompletableFutures sono stati introdotti in Java 8 (2014). Sono in effetti un'evoluzione dei Futures regolari, ispirati ai Future Ascoltabili di Google , parte della biblioteca di Guava . Sono Futures che ti permettono anche di mettere insieme attività in una catena. Puoi usarli per dire a un thread di lavoro di "andare a fare alcune attività X, e quando hai finito, vai a fare quest'altra cosa usando il risultato di X". Usando CompletableFutures, puoi fare qualcosa con il risultato dell'operazione senza realmente bloccare un thread in attesa del risultato. Ecco un semplice esempio:
/**
* A supplier that sleeps for a second, and then returns one
**/
public static class MySupplier implements Supplier<Integer> {
@Override
public Integer get() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//Do nothing
}
return 1;
}
}
/**
* A (pure) function that adds one to a given Integer
**/
public static class PlusOne implements Function<Integer, Integer> {
@Override
public Integer apply(Integer x) {
return x + 1;
}
}
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newSingleThreadExecutor();
CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new MySupplier(), exec);
System.out.println(f.isDone()); // False
CompletableFuture<Integer> f2 = f.thenApply(new PlusOne());
System.out.println(f2.get()); // Waits until the "calculation" is done, then prints 2
}
RxJava
RxJava è l'intera libreria per la programmazione reattiva creata su Netflix. A prima vista, sembrerà simile ai flussi di Java 8 . Lo è, tranne che è molto più potente.
Analogamente a Futures, RxJava può essere utilizzato per mettere insieme un insieme di azioni sincrone o asincrone per creare una pipeline di elaborazione. A differenza dei future, che sono monouso, RxJava funziona su flussi di zero o più elementi. Compresi flussi senza fine con un numero infinito di elementi. È anche molto più flessibile e potente grazie a un insieme incredibilmente ricco di operatori .
A differenza dei flussi di Java 8, RxJava ha anche un meccanismo di contropressione , che gli consente di gestire i casi in cui parti diverse della pipeline di elaborazione operano in thread diversi, a velocità diverse .
Il rovescio della medaglia di RxJava è che, nonostante la solida documentazione, è una libreria stimolante da imparare a causa del cambio di paradigma in questione. Il codice Rx può anche essere un incubo per il debug, specialmente se sono coinvolti più thread e, peggio ancora, se è necessaria la contropressione.
Se vuoi approfondire, c'è un'intera pagina di vari tutorial sul sito ufficiale, oltre alla documentazione ufficiale e Javadoc . Puoi anche dare un'occhiata ad alcuni dei video come questo che fornisce una breve introduzione a Rx e parla anche delle differenze tra Rx e Futures.
Bonus: Java 9 Reactive Streams
Reactive Streams di Java 9 aka Flow API sono un insieme di interfacce implementate da varie librerie di flussi reattivi come RxJava 2 , Akka Streams e Vertx . Consentono a queste librerie reattive di interconnettersi, preservando allo stesso tempo l'importante contropressione.