Pour exécuter certaines tâches en parallèle ou de manière asynchrone, je peux utiliser un ExecutorService: <T> Future<T> submit(Runnable task, T result);
ou l'API CompletableFuture: static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);
Outre le type de retour Future
contre CompletableFuture
, existe-t-il des différences remarquables. Ou quand utiliser quoi?
Et quelles sont les différences si j'utilise l'API CompletableFuture
avec la valeur par défaut Executor
(la méthode sans exécuteur)?
Outre le type de retour Future vs. CompletableFuture, existe-t-il des différences remarquables. Ou quand utiliser quoi?
C'est plutôt simple, vraiment. Vous utilisez la variable Future
lorsque vous souhaitez que le thread en cours d'exécution attende une réponse de calcul asynchrone. Un exemple de ceci est avec une fusion/tri parallèle. Triez à gauche de manière asynchrone, triez à droite de manière synchrone, attendez à gauche pour terminer (future.get()
), fusionnez les résultats.
Vous utilisez un CompleteableFuture
lorsque vous souhaitez qu'une action soit exécutée, avec le résultat après achèvement, de manière asynchrone à partir du thread exécuté. Par exemple, je souhaite effectuer des calculs de manière asynchrone et lorsque je calcule, écris les résultats sur un système. Le thread demandeur peut alors ne pas avoir besoin d'attendre un résultat.
Vous pouvez imiter l'exemple ci-dessus dans un seul exécutable Future, mais CompletableFuture
offre une interface plus fluide avec une meilleure gestion des erreurs.
Cela dépend vraiment de ce que vous voulez faire.
Et quelles sont les différences si j'utilise CompletableFutureApi avec Executor par défaut (la méthode sans exécuteur)?
Il déléguera à ForkJoin.commonPool()
qui est une taille par défaut pour le nombre de processeurs de votre système. Si vous effectuez une opération IO intensive (lecture et écriture dans le système de fichiers), vous devez définir le pool de threads différemment.
Si vous utilisez beaucoup de ressources en processeur, utilisez le pool commun.
CompletableFuture possède de riches fonctionnalités telles que le chaînage de plusieurs futures, la combinaison des futures, l'exécution de certaines actions après l'exécution future (à la fois de manière synchrone et asynchrone), etc.
Cependant, CompletableFuture n’est pas différent de Future en termes de performances. Même en combinant plusieurs instances de CompletableFuture (en utilisant .thenCombine et .join à la fin), aucune d'entre elles n'est exécutée à moins d'appeler la méthode .get et, pendant ce temps, le thread appelant est bloqué. Je pense qu'en termes de performance, ce n'est pas mieux que Future.
Faites-moi savoir s'il me manque un aspect de la performance ici.
Cela m'a permis de clarifier un peu plus la différence entre futur et completable: Différence entre futur et promesse
CompletableFuture est plus comme une promesse.