Tags : java8, CompletableFuture

Je vais aujourd’hui vous présenter les CompletableFuture de java 8.

Pour l’exemple, nous allons réaliser un petit programme Java permettant de récupérer le titre le plus long parmi les articles du blog.
Pour faire cela, nous allons récupérer la page archive du blog, pour ensuite récupérer chaque lien d’article et pour finir récupérer le titre des articles.

Méthode naïve

Commençons par la méthode naïve sans java8 :

Cette méthode a l’intérêt d’être très facilement compréhensible, par contre c’est beaucoup trop séquentiel, il faudrait pouvoir exécuter les requêtes en parallel et non de manière séquentiel.

Méthode à base de Future

Nous allons maintenant exécuter les requêtes en parallel à l’aide d’un bon vieux ExecutorService :

Cette méthode est beaucoup plus performante, mais un truc me gène :

boolean allDone = false;
while (!allDone) {
    allDone = true;
    for (Future<String> result : results) {
        if (!result.isDone()) {
            allDone = false;
            break;
        }
    }
    Thread.sleep(50);
}

Avoir du code technique de ce type là en plein milieu, ça me plait pas trop.

UPDATE : Comme on me l’a fait remarquer sur twitter, il est tout a fait possible de supprimer ce bloc, l’attente étant gérée par le get.
Cependant on ne voit plus de notion de “tout les traitements terminés”, ce qui dans un cas plus complexe peux être très utile.

Méthode à base de CompletableFuture

Nous allons maintenant transformer notre code pour utiliser les CompletableFuture de java8 :

Personnellement je trouve ce code beaucoup plus lisible et sans (ou très peu de) code technique.

Quelques détails sur l’API :

  • CompletableFuture.supplyAsync : permet d’exécuter un traitement en asynchrone, retourne le CompletableFuture correspondant.
  • CompletableFuture.allOf : Permet de récupérer un CompletableFuture correspondant à la fin de tous les CompletableFuture passés en paramètres.
  • CompletableFuture.thenApply : Execute un fonction une fois le CompletableFuture terminé. Cette fonction prend en paramètre l’objet du CompletableFuture est renvoie un autre type.

Performances

Voici les résultats des trois méthodes en terme de performances :

  • Méthode naïve : 2243ms
  • Méthode à base de Future : 310ms
  • Méthode à base de CompletableFuture : 230ms

Pour les curieux, l’ensemble de ma classe de test se trouve ici.