Futures
Les contrats à terme ont été introduits dans Java 5 (2004). Ce 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, le Future
contiendra ce résultat. Par exemple, une opération peut être une instance exécutable ou appelable soumise à un ExecutorService . L'émetteur de l'opération peut utiliser l' Future
objet pour vérifier si l'opération est terminée () ou attendre qu'elle se termine en utilisant la méthode bloquante get () .
Exemple:
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());
System.out.println(f.get());
}
CompletableFutures
CompletableFutures a été introduit dans Java 8 (2014). Ils sont en fait une évolution des Futures classiques, inspirés des Listenable Futures de Google , qui fait partie de la bibliothèque Guava . Ce sont des Futures qui vous permettent également d'enchaîner des tâches dans une chaîne. Vous pouvez les utiliser pour dire à un thread de travail de "faire une tâche X, et quand vous avez terminé, faites 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 réellement bloquer un thread pour attendre le résultat. Voici un exemple simple:
public static class MySupplier implements Supplier<Integer> {
@Override
public Integer get() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return 1;
}
}
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());
CompletableFuture<Integer> f2 = f.thenApply(new PlusOne());
System.out.println(f2.get());
}
RxJava
RxJava est une bibliothèque complète pour la programmation réactive créée chez Netflix. En un coup d'œil, il semblera similaire aux flux de Java 8 . C'est le cas, sauf que c'est beaucoup plus puissant.
De la même manière que Futures, RxJava peut être utilisé pour enchaîner un ensemble d'actions synchrones ou asynchrones pour créer un pipeline de traitement. Contrairement aux Futures, qui sont à usage unique, RxJava fonctionne sur des flux de zéro ou plusieurs éléments. Y compris des flux sans fin avec un nombre infini d'éléments. Il est également beaucoup plus flexible et puissant grâce à un ensemble incroyablement riche d'opérateurs .
Contrairement aux flux de Java 8, RxJava dispose également d'un mécanisme de contre- pression , qui lui permet de gérer les cas dans lesquels différentes parties de votre pipeline de traitement fonctionnent dans différents threads, à des taux différents .
L'inconvénient de RxJava est que malgré la documentation solide, c'est une bibliothèque difficile à apprendre en raison du changement de paradigme impliqué. Le code Rx peut également être un cauchemar à déboguer, en particulier si plusieurs threads sont impliqués, et pire encore, si une contre-pression est nécessaire.
Si vous voulez y entrer, il y a toute une page de divers tutoriels sur le site officiel, ainsi que la documentation officielle et Javadoc . Vous pouvez également regarder certaines des vidéos telles que celle-ci qui donne une brève introduction à Rx et parle également des différences entre Rx et Futures.
Bonus: flux réactifs Java 9
Les flux réactifs de Java 9, également appelés API Flow, sont un ensemble d'interfaces implémentées par diverses bibliothèques de flux réactifs telles que RxJava 2 , Akka Streams et Vertx . Ils permettent à ces bibliothèques réactives de s'interconnecter, tout en préservant la contre-pression importante.