Exécuteur, ExecutorService, Exécuteur - 1

« Salut Amigo ! »

"Rien n'est parfait lorsqu'il est créé pour la première fois. Il en va de même pour les threads. Avec le temps, les créateurs de Java ont été convaincus des lacunes de l'interface Runnable. Elle ne supportait pas le lancement d'exceptions et ne permettait pas de découvrir le résultat de l'exécution de tâches…"

"L'interface Runnable est plus adaptée aux grandes tâches indépendantes qu'aux petites sous-tâches que vous souhaitez exécuter une douzaine à la fois, puis collecter leurs résultats."

"C'est pourquoi l' interface Callable a été inventée. Elle est bien mieux adaptée à l'exécution parallèle de petites tâches que Runnable et Thread, en partie parce qu'il s'agit d'une interface générique."

"Voici une implémentation typique de l'interface :"

Exemple
class ReverseString implements Callable<String>
{
 String str;

 ReverseString(String str)
 {
  this.str = str;
 }

 public String call() throws Exception
 {
  StringBuilder builder = new StringBuilder(str);
  builder.reverse();
  return builder.toString();
 }
}

"Contrairement à Runnable , nous devons ici remplacer la méthode call, qui renvoie un résultat du type spécifié par l'argument type. Cette approche est beaucoup plus pratique que la méthode run de l'interface Runnable, qui renvoie void. Parfois, les développeurs devaient trouver diverses solutions de contournement pour obtenir le résultat d'un thread."

"Je vois."

"Et maintenant, regardez comment Callable peut fonctionner avec ThreadPoolExecutor :

"Tout d'abord, la méthode submit de la classe ThreadPoolExecutor renvoie un objet Future paramétré. Vous pouvez utiliser cet objet pour savoir si une tâche est terminée et pour obtenir le résultat."

"Voici comment cela fonctionne:"

Exemple
// 1. Create a ThreadPoolExecutor
ExecutorService service = Executors.newFixedThreadPool(5);

// 2. Add a task to it
Future<String> task = service.submit(new ReverseString("Amigo"));

// 3. Wait until the task is done
while(!task.isDone())
{
 Thread.sleep(1);
}

// 4. Try to get the result
//We will get either the result, or an exception if one occurred while the task was being executed
try
{
 System.out.println("Full string : " + task.get());
}
catch (Exception ie)
{
 ie.printStackTrace(System.err);
}
  
// 5. Stop the ThreadPool.
service.shutdown();

« Loin ! J'aime particulièrement la classe Future. Quelles méthodes a-t-elle ?

"Voici les plus intéressants :"

Méthode Description
boolean cancel(boolean mayInterrupt);
Arrête la tâche.
boolean isCancelled();
Renvoie vrai si la tâche a été arrêtée.
boolean isDone();
Renvoie true si la tâche est en cours d'exécution.
V get() throws InterruptedException, ExecutionException;
Renvoie le résultat de la méthode d'appel ou lève une exception si elle s'est produite.

"Cool ! Ainsi, vous pouvez également arrêter des tâches."

"Ne vous fiez pas trop à cela - tous les threads ne peuvent pas s'arrêter. Mais si une tâche est toujours dans la file d'attente, cela fonctionnera bien."

"J'aime cette approche. C'est beaucoup plus pratique que de créer vous-même des threads et d'essayer ensuite d'en tirer un résultat."

"Génial. C'est là que nous finirons aujourd'hui."