web-dev-qa-db-fra.com

Différence entre CompletableFuture, Future et RxJava's Observable

J'aimerais connaître la différence entre CompletableFuture, Future et ObservableRxJava.

Ce que je sais, c’est que tous sont asynchrones mais

Future.get() bloque le fil

CompletableFuture donne les méthodes de rappel

RxJava Observable --- similaire à CompletableFuture avec d'autres avantages (non sûr)

Par exemple: si le client a besoin de faire plusieurs appels de service et que nous utilisons Futures (Java) Future.get() sera exécuté séquentiellement ... voudrait savoir comment il est meilleur dans RxJava ..

Et la documentation http://reactivex.io/intro.html dit

Il est difficile d'utiliser Futures pour composer de manière optimale des flux d'exécution asynchrones conditionnels (ou impossible, car les latences de chaque demande varient au moment de l'exécution). Cela peut être fait, bien sûr, mais cela devient rapidement compliqué (et donc sujet à des erreurs) ou il se bloque prématurément sur Future.get (), ce qui élimine les avantages d'une exécution asynchrone.

Vraiment intéressé de savoir comment RxJava résoud ce problème. J'ai trouvé difficile à comprendre à partir de la documentation.

160
shiv455

Futures

Futures ont été introduits dans Java 5 (2004). Ils sont essentiellement des espaces réservés pour le résultat d'une opération qui n'est pas encore terminée. Une fois l'opération terminée, la Future contiendra ce résultat. Par exemple, une opération peut être une instance Runnable ou Callable qui est soumise à un ExecutorService . L'émetteur de l'opération peut utiliser l'objet Future pour vérifier si l'opération isDone () , ou attendre qu'elle se termine à l'aide de la méthode de blocage get () .

Exemple:

/**
* 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 ont été introduits dans Java 8 (2014). Il s’agit en fait d’une évolution des contrats à terme classiques, inspirés par la bibliothèque Listenable Futures de Google, qui fait partie de la bibliothèque Guava . Ce sont des contrats à terme qui vous permettent également d’enchaîner des tâches dans une chaîne. Vous pouvez les utiliser pour dire à un thread de travail "d'aller faire une tâche X, et quand vous aurez fini, allez faire cette autre chose en utilisant le résultat de X". En utilisant CompletableFutures, vous pouvez faire quelque chose avec le résultat de l'opération sans bloquer réellement un thread qui attend le résultat. Voici un exemple simple:

/**
* 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 est une bibliothèque complète pour programmation réactive créée à Netflix. En un coup d'œil, cela ressemblera à les flux de Java 8 . C'est, sauf que c'est beaucoup plus puissant.

Comme dans Futures, RxJava peut être utilisé pour enchaîner un ensemble d’actions synchrones ou asynchrones afin de créer un pipeline de traitement. Contrairement à Futures, qui sont à usage unique, RxJava fonctionne sur streams de zéro ou plusieurs éléments. Y compris les flux sans fin avec un nombre infini d'éléments. Il est également beaucoup plus flexible et puissant grâce à un nombre incroyablement riche ensemble d’opérateurs .

Contrairement aux flux de Java 8, RxJava dispose également d'un mécanisme contrepression , ce qui lui permet de gérer les cas dans lesquels différentes parties de votre pipeline de traitement fonctionnent dans différents threads, à différents tarifs.

L'inconvénient de RxJava réside dans le fait qu'en dépit d'une documentation solide, c'est une bibliothèque difficile à apprendre en raison du changement de paradigme impliqué. Le code Rx peut également être un cauchemar pour le débogage, en particulier si plusieurs threads sont impliqués, et même pire - si une contre-pression est nécessaire.

Si vous voulez vous lancer, il y a un ensemble page de divers tutoriels sur le site officiel, plus le document officiel documentation et Javadoc . Vous pouvez également consulter certaines vidéos telles que celle-ci , qui donne une brève introduction à Rx et décrit également les différences entre Rx et Futures.

Bonus: Java 9 flux réactifs

flux réactifs de Java 9 aka API de flux sont un ensemble d'interfaces implémentées par différentes flux réactifs bibliothèques telles que RxJava 2 , Akka Streams , et Vertx . Ils permettent l’interconnexion de ces bibliothèques réactives, tout en préservant la contre-pression primordiale.

238
Malt

Je travaille avec Rx Java depuis la 0.9, maintenant à la version 1.3.2 et migrant bientôt vers la version 2.x. Je l'utilise dans un projet privé sur lequel je travaille déjà depuis 8 ans.

Je ne programmerais plus du tout sans cette bibliothèque. Au début, j'étais sceptique, mais vous devez créer un autre état d'esprit complet. Calme difficile au début. Je regardais parfois les billes pendant des heures .. lol

C’est juste une question de pratique et d’approfondissement des connaissances (contrat d’observables et d’observateur), une fois que vous y serez arrivé, vous détesterez le faire autrement.

Pour moi, il n'y a pas vraiment d'inconvénient à cette bibliothèque.

Cas d'utilisation: j'ai une vue de moniteur contenant 9 jauges (cpu, mem, réseau, etc.). Lors du démarrage de la vue, celle-ci s'abonne à une classe de surveillance du système qui renvoie un observable (intervalle) contenant toutes les données des 9 compteurs. Il poussera chaque seconde un nouveau résultat à la vue (donc pas de scrutation !!!). Cet observable utilise une flatmap pour extraire simultanément (async!) Des données de 9 sources différentes et compresser le résultat dans un nouveau modèle que votre vue obtiendra sur onNext ().

Comment diable allez-vous pouvoir faire cela avec des futures, des compléments, etc ... Bonne chance! :)

Rx Java résout beaucoup de problèmes de programmation pour moi et rend beaucoup plus facile ...

Avantages:

  • Statels !!! (chose importante à mentionner, le plus important peut-être)
  • Gestion de fil hors de la boîte
  • Construire des séquences qui ont leur propre cycle de vie
  • Tout est observable, donc l'enchaînement est facile
  • Moins de code à écrire
  • Jarre simple sur classpath (très léger)
  • Très concurrente
  • Pas de rappel enfer
  • Basé sur l'abonné (contrat étroit entre le consommateur et le producteur)
  • Stratégies de contre-pression (disjoncteur similaire)
  • Splendid gestion des erreurs et la récupération
  • Très belle documentation (billes <3)
  • Contrôle complet
  • Beaucoup plus ...

Inconvénients: - Difficile à tester

18
Kristoffer