Differenza tra CompletableFuture, Future e RxJava's Observable


194

Vorrei sapere la differenza tra CompletableFuture, Futuree Observable RxJava.

Quello che so è che tutti sono asincroni ma

Future.get() blocca il thread

CompletableFuture fornisce i metodi di callback

RxJava Observable--- simile ad CompletableFuturealtri vantaggi (non sono sicuro)

Ad esempio: se il client deve effettuare più chiamate di servizio e quando utilizziamo Futures(Java) Future.get()verrà eseguito in sequenza ... vorrebbe sapere come è meglio in RxJava ..

E la documentazione http://reactivex.io/intro.html dice

È difficile utilizzare i Futures per comporre in modo ottimale flussi di esecuzione asincroni condizionali (o impossibili, poiché le latenze di ciascuna richiesta variano in fase di esecuzione). Questo può essere fatto, ovviamente, ma diventa rapidamente complicato (e quindi soggetto a errori) o si blocca prematuramente su Future.get (), il che elimina il beneficio dell'esecuzione asincrona.

Davvero interessato a sapere come RxJavarisolve questo problema. Ho trovato difficile capire dalla documentazione.


Hai letto la documentazione per ciascuno? Non ho familiarità con RxJava, ma la documentazione appare estremamente accurata a colpo d'occhio. Non sembra particolarmente paragonabile ai due futuri.
FThompson,

ho attraversato ma non sono in grado di capire quanto sia diverso dai futuri Java ... correggimi se sbaglio
shiv455

In che modo gli osservabili sono simili ai futures?
FThompson,

2
vorrei sapere dove è diverso come è diverso nella gestione dei thread ?? EX: Future.get () blocca il thread .... come verrà gestito in Observable ???
shiv455,

2
almeno è un po 'confuso per me ... una differenza di alto livello sarebbe davvero utile !!
shiv455,

Risposte:


281

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, Futureconterrà quel risultato. Ad esempio, un'operazione può essere un'istanza Runnable o Callable inviata a ExecutorService . Il mittente dell'operazione può utilizzare l' Futureoggetto 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.


Sarebbe bello dare un esempio di come Rx fa questo
Zinan Xing,

Quindi, usando Reactive Streams, possiamo mescolare RxJava, Akka e Vertx in una sola applicazione?
IgorGanapolsky,

1
@IgorGanapolsky Sì.
Malt,

In CompletableFutures utilizziamo i metodi di callback, questi metodi di callback si bloccano anche se l'output di un metodo è l'input di un altro callback. Come blocco futuro con la chiamata Future.get (). Perché si dice che Future.get () sta bloccando la chiamata mentre CompletableFutures non blocca. Per favore, spiega
Deepak,

1
@Federico Certo. Ognuno Futureè un segnaposto per un singolo risultato che può o non può ancora essere stato completato. Se esegui nuovamente la stessa operazione, otterrai una nuova Futureistanza. RxJava si occupa di flussi di risultati che possono arrivare in qualsiasi momento. Una serie di operazioni può quindi restituire un singolo osservabile RxJava che produrrà un sacco di risultati. È un po 'come la differenza tra una singola busta postale e un tubo pneumatico che continua a pompare la posta.
Malt,

21

Lavoro con Rx Java dalla 0.9, ora alla 1.3.2 e presto migrando alla 2.x Lo uso in un progetto privato dove lavoro già da 8 anni.

Non programmerei più senza questa libreria. All'inizio ero scettico ma è un altro stato d'animo completo che devi creare. Tranquillo difficile all'inizio. A volte guardavo i marmi per ore .. lol

È solo una questione di pratica e conoscere veramente il flusso (noto anche come contratto di osservabili e osservatore), una volta arrivato lì, odierai farlo diversamente.

Per me non c'è davvero un aspetto negativo in quella biblioteca.

Caso d'uso: ho una vista monitor che contiene 9 indicatori (CPU, mem, rete, ecc ...). All'avvio della vista, la vista si iscrive a una classe di monitor di sistema che restituisce un osservabile (intervallo) che contiene tutti i dati per i 9 metri. Spingerà ogni secondo un nuovo risultato alla vista (quindi non polling !!!). Questo osservabile usa una flatmap per recuperare simultaneamente (asincramente!) I dati da 9 fonti diverse e comprime il risultato in un nuovo modello che la tua vista otterrà su onNext ().

Come diavolo lo farai con i futures, i completabili ecc ... Buona fortuna! :)

Rx Java risolve molti problemi di programmazione per me e rende in un modo molto più semplice ...

vantaggi:

  • Statelss !!! (cosa importante da menzionare, forse la più importante)
  • Gestione del thread out of the box
  • Costruisci sequenze che hanno il loro ciclo di vita
  • Tutto è osservabile, quindi concatenarsi è facile
  • Meno codice da scrivere
  • Vaso singolo su classpath (molto leggero)
  • Altamente concorrente
  • Nessun inferno di richiamata più
  • Basato su abbonati (contratto stretto tra consumatore e produttore)
  • Strategie di contropressione (interruttore simile)
  • Splendida gestione e recupero degli errori
  • Documentazione molto bella (marmi <3)
  • Controllo completo
  • Molti altri ...

Svantaggi: - Difficile da testare


13
~ " Non programmerei più senza questa libreria. " Quindi RxJava è la fine di tutti per tutti i progetti software?
IgorGanapolsky,

È utile anche se non ho Stream di eventi asincroni?
Mukesh Verma,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.