Vous êtes sur la page 1sur 18

Le framework Executor

Par ramius

www.siteduzero.com

Dernire mise jour le 24/08/2011

Sommaire

1/17

Sommaire
Sommaire ........................................................................................................................................... 1 Informations sur le tutoriel ................................................................................................................... 0 Le framework Executor ....................................................................................................................... 2
Informations sur le tutoriel ................................................................................................................................................. 2 Un petit rappel ................................................................................................................................................................... 2
L'utilisation des threads ............................................................................................................................................................................................... 2

Les bases .......................................................................................................................................................................... 3


Un peu d'histoire ......................................................................................................................................................................................................... 3 Les base du framework Executor ................................................................................................................................................................................ 4 Exemple ...................................................................................................................................................................................................................... 6

Les pools de threads ......................................................................................................................................................... 6


Un exemple un peu plus parlant ................................................................................................................................................................................. 9

Callable<V> et Future<V> ............................................................................................................................................... 10 Un peu de structure dans nos programmes .................................................................................................................... 12


Le service de terminaison ......................................................................................................................................................................................... 13 Lire aussi ................................................................................................................................................................................................................... 17

www.siteduzero.com

Le framework Executor

2/17

Le framework Executor
Bonjour tous, Tout d'abord, sachez que la programmation concurrente est un sujet trs vaste et souvent complexe, rempli de piges et de comportements tous plus tranges les uns que les autres . Dans son big-tuto, Cysboy a introduit les threads et a illustr leur complexit. Je ne vais pas aborder ici les moyens d'assurer la thread-safety (le fait qu'un objet se comporte correctement quand plusieurs threads y accdent), cela fera peut-tre l'objet d'un futur tutoriel. Pour en revenir aux threads, JAV 5 a introduit un nouveau moyen d'excuter les tches en A parallles : le framework Executor.

Informations sur le tutoriel


Auteur : ramius Difficult : Licence :

Je ne vais pas vous l'expliquer en intgralit, mais vous devriez tre mme d'en comprendre les grandes lignes.

Je pars du principe que vous avez dj une certaine pratique de Java et que vous avez dj entendu le mot thread. Si les collections, les gnriques et la programmation Java en gnral vous sont compltement trangers, commencez par le tutoriel de Cysboy.

Sans plus attendre amis zros, voyons ce que nous rserve le framework Executor. Sommaire du tutoriel :

Un petit rappel Les bases Les pools de threads Callable<V> et Future<V> Un peu de structure dans nos programmes Q.C.M.

Un petit rappel L'utilisation des threads


Les threads sont omniprsents dans les programmes java. V otre JVM (Java Virtual Machine), qui se charge d'excuter votre programme, va crer des threads votre insu : les threads qui s'occupent des oprations de nettoyage de la mmoire et le thread d'excution principal de votre programme. Je profite galement de ce court rappel sur les threads pour prciser certaines choses : L'ordre d'excution des threads n'est pas garanti. J'entends par l que, code quivalent, l'ordre d'xecution des threads peut changer. Je vois souvent les dbutants se poser des questions quand l'utilit de l'encapsulation ou l'utilisation du mot-cl final dans le code. Je ne vous dirai que ceci : l'encapsulation et les objets immuables sont vos meilleurs allis pour vous en sortir dans un environnement multi-threads en java (ceci tant un tuto sur java je n'largirais pas le dbat d'autres langages). Je vous prcise au passage que l'encapsulation n'a que trs rarement un impact sur les performances mais c'est un autre dbat.

www.siteduzero.com

Le framework Executor

3/17

Je ne doute pas une seule seconde que les threads n'ont absolument aucun secret pour vous mais juste pour vous rafraichir la mmoire, gnralement on cr un thread de cette faon : On implmente l'interface java.lang.Runnable Code : Java public class MonRunnable implements Runnable { @Override public void run(){ System.out.println("Travail effectuer"); } }

et on l'enveloppe dans un thread : Code : Java public class Main { public static void main(String[] args){ //On crer notre thread avec notre tache executer Thread t = new Thread(new MonRunnable()); //On lance le thread t.start();

Je sais, vous le saviez dj.

Les bases Un peu d'histoire


Nous sommes en 2004, Java 5 (Tiger) viens de sortir. Comme toutes les versions, celle-ci apporte sont lots de nouveauts dont l'auto-boxing, auto-unboxing, les gnriques et la nouvelle API de concurrence. Dsigne sous le doux nom de JSR 166 (http://www.jcp.org/en/jsr/detail?id=166) et conu sous la direction (il n'tait pas le seul bien sur) de Doug Lea, enseignant l'universit d'tat d'Oswego aux Etats-Unis, cette JSR introduit, entre autres choses, un nouveau framework d'xecution des tches connu sous le nom de Framework Executor. 6 ans plus tard, Executor semble peu connu voir totalement ignor dans le programme des universits. L'ide d'Executor et des autres outils prsents dans le package java.util.concurrent, est de pouvoir choisir facilement la politique d'excution de nos tches. Qu'est-ce qu'une politique d'excution ? Et bien c'est relativement simple. La politique d'excution rpond globalement 3 questions : Quelles tches vont tre excutes ? Dans quel ordre ? Combien de ses tches peut on excuter en parallle ?

Avant Java 5, c'tait aux dveloppeurs dimplmenter les classes ncessaire la politique qu'ils souhaitaient mettre en place (Files d'excutions, pool de threads...).

www.siteduzero.com

Le framework Executor
Ceci tant dit, explorons Executor.

4/17

Les base du framework Executor


Autant le dire tout de suite : vous

ne manipulez plus les threads directement !

L'abstraction de base que vous allez utiliser est l'interface Executor. Code : Java public interface Executor { } void execute(Runnable command);

J'aimerais ici faire un petit apart sur les interfaces. Comme l'a trs bien expliqu Cysboy dans son tutoriel les interfaces permettent de crer des super-types et donc de permettre un polymorphisme. De ces deux choses dcoulent le principal intrt des interfaces, le dcouplage. Je m'explique : Une interface A dcrit un certain nombres d'oprations Code : Java public interface A { void methodeA(); void methodeB();

On veut, qelle que soit la classe qui implmente A, faire un traitement particulier. V ous pouvez sans problme crire une mthode qui prend en paramtre une interface, car vous savez quelles mthodes seront implmentes dans les classes qui implmentent votre interface. Si la classe qui implmente l'interface A change (pour une autre classe d'implmentation plus adapte par exemple), la mthode execute (voir exemple ci-aprs) n'aura pas besoin d'tre change. C'est la raison pour laquelle on utilise des interfaces. Code : Java public class Execution { public void execute(A a) { a.methodeA(); a.methodeB();

Crer un framework bas sur les interfaces permet donc une grande souplesse dans l'excution des tches. V ous pourrez excuter n'importe quelle tche qui implmentent Runnable. Comme dit prcdemment, les executors excutent tout comme les threads, des Runnables. Nous allons reprendre l'exemple prcdent en utilisant Executor cette fois : Au lieu de crer un thread avec new Thread(...), nous allons utiliser Executor qui fournit une mthode pour produire le mme effet : la mthode newSingleThreadExecutor().

www.siteduzero.com

Le framework Executor
Code : Java public class Main { public static void main(String[] args) { Executor executor = Executors.newSingleThreadExecutor(); executor.execute(new MonRunnable());

5/17

} }

Il y a 3 interfaces connaitre : Executor : Pour l'excution des "Runnables" ExecutorService : Pour l'excution des tches "Runnables" et "Callables"(les Callables seront expliqus par la suite) ScheduledExecutorService : Pour l'excution des tches priodiques (qui se rpte dans le temps) et diffre (la tche doit commencer dans 60 secondes par exemple)

La relation entre ces interfaces est la suivante :

Pour les zros un peu allergique l'UML hrite de Executor.

: ScheduledExecutorService hrite de ExecutorService, et ExecutorService

Cependant vous le savez, on n'instancie pas une interface. Pour crer les bons objets nous allons nous en remettre une seule classe : Executors. Notez bien Executor ; C'est une classe qui contient toutes les mthodes statiques ncessaire la cration d'objets du framework Executor. Dans l'exemple prcdent j'ai utilis cette classe : Code : Java public class Main {

www.siteduzero.com

Le framework Executor
public static void main(String[] args) { Executor executor = Executors.newSingleThreadExecutor(); executor.execute(new MonRunnable());

6/17

La mthode newSingleThreadExecutor(); renvoie un executor mono-thread. Je vous rappelle que vous ne manipulez pas les threads directement. Executor contient plusieurs fabriques qui ne renvoient que des executors mono-thread : Executors.newSingleThreadExecutor() : Executor mono-thread classique Executors.newSingleThreadScheduledExecutor() : Executor mono-thread pour les tches priodiques Nous verrons les autres mthodes par la suite.

Exemple
Prcedemment je vous ai montr le newSingleThreadExecutor() donc je vais vous montrer le newSingleThreadScheduledExecutor(). Pour information pour faire des tches priodiques avec des threads on utilisait les "TimerTask" et la classe utilitaire "Timer". Cependant Timer ne s'appuyait que sur le temps absolu (de votre horloge systme) qui risquait d'tre change, alors que Executor ne sappuie que sur le temps relatif.

Ceci tant dit, sans plus attendre voici un exemple de tche excut toutes les secondes. Code : Java public class Main { public static void main(String[] args){ ScheduledExecutorService execute = Executors.newSingleThreadScheduledExecutor(); //Execute MonRunnable toutes les secondes execute.scheduleAtFixedRate(new MonRunnable(), 0, 1, TimeUnit.SECONDS); } }

Lnumration TimeUnit apporte une plus grande clart au code. Cela vite d'avoir crire le temps en milli-secondes, ce qui est illisible arriv un certain point. Simple non ?

Les pools de threads


Bon les excutions mono-thread c'est bien gentil mais je ne veux pas attendre qu'une tche se termine avant de faire la suivante moi ! Il est o le paralllisme sinon ...

www.siteduzero.com

Le framework Executor
Merci de poser la question Comme vous avez sans doute pu le voir si vous dveloppez dans un IDE (h oui dans le bloc note il n'y a pas d'autocompltion), la classe Executors possde des mthodes aux noms un peu trange : newFixedThreadPool(), newScheduledThreadPool(), newCachedThreadPool()...

7/17

Si vous ne savez pas ce qu'est un pool d'objets, et bien pour simplifier disons que c'est une collection d'objets crs et initialiss puis mis en mmoire. On les utilise quand le cot de cration et d'initialisation d'un objet est assez important. Le fait de mettre certains objets en mmoire peut augmenter les performances dans certain cas mais je ne vais pas rentrer dans les dtails de la performance en java. Les tailles des pools de threads ne sont pratiquement jamais codes en dur. La taille des pools dpend en effet des ressources. Passer de 3 100 processeurs n'est pas ngligeable et le programme doit prendre en compte ces changements. Il existe une mthode pour rcuprer dynamiquement le nombre de processeurs disponibles: Code : Java int proc = Runtime.getRuntime().availableProcessors();

Bref, revenons notre Executors. Le but ici est de ne pas utiliser le mme thread pour toutes les tches mais d'utiliser un thread diffrent pour chacune. Donc il n'y a plus besoin d'attendre qu'une tche soit finie pour excuter la suivante. Allons-y pas pas, nous allons commencer par modifier la classe MonRunnable pour observer dans quel thread on se trouve. La nouvelle classe Runnable : Code : Java public class MonRunnable implements Runnable { @Override public void run() { try { //On simule un traitement long en mettant en pause le Thread pendant 4 secondes Thread.sleep(4000); //On affiche le nom du thread o on se trouve System.out.println("Execution dans le thread " + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } } }

Nous allons tout d'abord l'excuter en mono-thread, c'est dire un thread pour toutes nos tches. Code : Java public class Main { public static void main(String[] args) { //La liste qui va stocker les taches effectuer

www.siteduzero.com

Le framework Executor
List<Runnable> runnables = new ArrayList<Runnable>(); //On crer 4 taches (instance de MonRunnable) runnables.add(new MonRunnable()); runnables.add(new MonRunnable()); runnables.add(new MonRunnable()); runnables.add(new MonRunnable()); //Notre executor mono-thread ExecutorService execute = Executors.newSingleThreadExecutor(); //La mthode qui se charge de l'excution des tches executeRunnables(execute, runnables); } public static void executeRunnables(final ExecutorService service, List<Runnable> runnables){ for(Runnable r : runnables){ service.execute(r); } //On ferme l'executor une fois les taches finies //En effet shutdown va attendre la fin d'excution des tches service.shutdown();

8/17

} }

Rsultat l'excution:

Modifions le code pour utiliser un pool de threads : chaque thread est lanc en parallle et excute la tche qui lui est ddie. (j'ai comment le code pour que vous compreniez). Code : Java public class Main { public static void main(String[] args){ List<Runnable> runnables = new ArrayList<Runnable>(); runnables.add(new runnables.add(new runnables.add(new runnables.add(new MonRunnable()); MonRunnable()); MonRunnable()); MonRunnable());

//Cette fois on crer un pool de 10 threads maximum ExecutorService execute = Executors.newFixedThreadPool(10); } executeRunnables(execute, runnables);

public static void executeRunnables(final ExecutorService service, List<Runnable> runnables){ //On excute chaque "Runnable" de la liste "runnables" for(Runnable r : runnables){

www.siteduzero.com

Le framework Executor
service.execute(r); } service.shutdown();

9/17

} }

Rsultat l'excution :

Executor facilite grandement l'excution de tches en parallles. Si tous les threads du pool sont occups les tches sont places dans une file d'attente jusqu' ce qu'un thread soit libre.

Un exemple un peu plus parlant


Les pools de threads sont gnralement utiliss pour excuter des tches homognes et indpendantes. Les serveurs qui traitent des requtes sont un excellent exemple d'utilisation. Les clients qui se connectent au serveur sont indpendants et le traitement est toujours le mme. Je vous renvoie au cours de SoftDeath "Introduction aux sockets", pour bien comprendre cet exemple. Nous allons donc mettre en place un simple serveur multi-threads qui va traiter les connexions entrantes dans un thread diffrent. Mais au lieu de crer un thread manuellement chaque connexion et donc grer son cycle de vie manuellement, nous allons utiliser un pool de threads qui va faire une taille bien dfinie pour tre sur de contrler le nombre de threads crs. Code : Java public class ServerLauncher { public static void main(String[] args){ //On se sert d'un pool de thread pour limiter le nombre de threads //en mmoire final ExecutorService service = Executors.newFixedThreadPool(100); ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(10000); int i = 0; while (true) { try { final Socket socket = serverSocket.accept(); //On traite la requte via notre executor service.execute(new Runnable(){ @Override public void run() { traitementRequete(socket); }

www.siteduzero.com

Le framework Executor
}); } catch (IOException e) { e.printStackTrace(); }

10/17

} }

} } catch (IOException e) { e.printStackTrace(); } finally { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } }

Le traitement des requtes dans un pool permet de contrler le nombre de threads crs. La cration illimite de threads est toujours dangereuse.

Callable<V> et Future<V>
Maintenant que vous savez comment excuter des tches j'aimerais attirer votre attention sur l'interface java.lang.Runnable. Pour rappel voici l'interface Runnable : Code : Java public interface Runnable { } public void run();

Cette interface souffre de deux limitations: La mthode run() ne peut renvoyer aucune valeur(void) Vous ne pouvez lancer aucune exception

Pour pallier ces deux problmes, une nouvelle interface a t dveloppe: (java.util.concurrent.Callable) Code : Java public interface Callable<V> { } public V call() throws Exception;

Callable<V>

V ous pouvez ainsi renvoyer le rsultat d'un calcul qui s'est droul dans la fonction call() sans avoir crer une variable globale,

www.siteduzero.com

Le framework Executor
ou passer en paramtre un objet pour stocker le rsultat. L'exemple suivant est effectivement inutile, mais illustre bien l'implmentation de Callable<V>. Code : Java public class MonCallable implements Callable<Integer> { @Override public Integer call() throws Exception { try { Thread.sleep(4000); //Traitement.... System.out.println("Dans le Callable"); } catch(InterruptedException e){ throw new Exception("Thread interrompu ; cause " + e.getMessage()); } return 3;//On peut retourner une valeur } }

11/17

De la mme manire que les "Runnables", vous pouvez utiliser les Executors pour soumettre des Callables. Cependant, nous n'utiliserons pas la mthode EXECUTE mais SUBMIT. Code : Java public class Main { public static void main(String[] args) { ExecutorService execute = Executors.newSingleThreadExecutor(); execute.submit(new MonCallable()); System.out.println("Apres submit"); } } execute.shutdown();

Je vous rappelle que les oprations sont asynchrones, donc l'excution "Apres submit" va s'afficher avant "Dans le Callable"

Je veux rcuprer le rsultat du Callable un instant prcis je fais comment ? J'utilise la mthode join() des threads, c'est a ?

Heureusement que vous tes la pour posez les questions Et bien non en fait, la methode submit(Callable<V> callable); renvoie un objet

Future<V>.

Qu'est-ce-que c'est que ce truc ??


www.siteduzero.com

Le framework Executor
Un Future<V> reprsente le cycle de vie d'une tche. Future<V> est bien sr une interface et submit renvoie un objet qui implmente cette interface; En loccurrence FutureTask. Rien que pour vous zros, voici l'interface Future<V> : Code : Java public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException, CancellationException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, CancellationException, TimeoutException; }

12/17

Revenons ma votre question. Future<V> possde une mthode bien pratique get() qui permet de rcuprer le rsultat envelopp dans l'objet FutureTask. On s'en sert de la faon suivante : Code : Java public class Main { public static void main(String[] args) { ExecutorService execute = Executors.newSingleThreadExecutor(); //On rcupre un objet Future<V> Future<Integer> future = execute.submit(new MonCallable()); try { //future.get() est bloquant, l'excution attend le resultat //et on l'affiche dans la console. System.out.println("Resultat du Callable " + future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("Apres submit"); } execute.shutdown();

Rsultat de l'excution :

Callable est une abstraction bien suprieure Runnable. Outre le fait de pouvoir renvoyer des rsultats qui ne nous sert parfois rien, le fait de pouvoir lever des exceptions n'est pas prendre la lgre.

Un peu de structure dans nos programmes


En matire d'architecture logicielle on en apprend tous les jours. Les experts de la JSR 166 nous apportent des solutions efficaces

www.siteduzero.com

Le framework Executor

13/17

ce qui nous vitent de chercher des solutions des problmes complexes. Comprenez moi bien, je ne vous empche pas d'implmenter vos propres solutions et je vous encourage comprendre et rflchir de nouvelles possibilits, mais pour le bien de votre application utilisez plutt celles prsentes dans le JDK. Pour les applications concurrentes les solutions ne manquent pas comme le service de terminaison.

Le service de terminaison
Un service de terminaison rpond la problmatique suivante : Comment rcuprer les rsultats d'un grand nombre de tches correctement et quand ils sont disponibles ? En ralit il y a plusieurs faon, plus ou moins bonnes, de le faire mais Executor nous en fournit une trs efficace : CompletionService. CompletionService utilise les files, c'est dire le modle producteursconsommateurs. C'est un modle assez simple, les producteurs crent les tches et les soumettent une file, les consommateurs retirent la premire tche et l'excute librant ainsi une nouvelle place dans la file pour une tche future. CompletionService permet de rcuprer un rsultat ds qu'il est disponible, on obtient alors une meilleure ractivit de l'application. CompletionService est une interface et sa classe d'implmentation, prsente dans le JDK et que nous allons utiliser ici, est ExecutorCompletionService. L'approche est la suivante: Nous allons rcuprer une liste de tches excuter et nous allons traiter les rsultats quand ceux-ci sont disponibles. Dans un premier temps, il faut crer les tches qui vont tre excutes. Pour simuler un calcul long, nous allons utiliser Thread.sleep(), la tche prendra en paramtres un entier qui correspondra au nombre de secondes pendant lesquelles le thread sera "endormi". Code : Java public class Task implements Callable<Integer> { private final int sleepTime; public Task(int n) { sleepTime = n; } @Override public Integer call() throws Exception { Thread.sleep(1000 * sleepTime); return sleepTime;

} }

V ous pouvez imaginer que dans la fonction call() se trouve en ralit un calcul trs important qui va prendre plus ou moins de temps en fonction de l'entier pass en paramtre. A prsent que notre classe reprsentant une tche est dclare, nous allons crer plusieurs de ces tches puis les excuter. Code : Java public class TestTask { public static void main(String[] args) { //Notre liste qui va contenir toutes les tches List<Callable<Integer>> taches = new ArrayList<Callable<Integer>>(); //On cr 4 tches avec un paramtre pour le //Thread.sleep() diffrent. Callable<Integer> tache1 = new Task(1); Callable<Integer> tache2 = new Task(5); Callable<Integer> tache3 = new Task(10);

www.siteduzero.com

Le framework Executor
Callable<Integer> tache4 = new Task(2); //On ajoute ces taches la liste taches.add(tache1); taches.add(tache2); taches.add(tache3); taches.add(tache4); pouvoir //On instancie un executor contenant 10 threads pour

14/17

//excuter nos actions en parallles ExecutorService executor = Executors.newFixedThreadPool(10);

Jusque l rien de nouveau. Si cela vous parait flou, revenez en arrire dans le tutoriel avant de continuer. Nous avons donc nos tches et notre executor qui va traiter ces tches. C'est ici que nous allons introduire notre service de terminaison : ExecutorCompletionService. Le constructeur de cette classe est trs simple : il prend en paramtre un Executor. Code : Java //Le type entre les chevrons dpend du type de vos Callables. //Si vous avez cr des Callable<String> alors vous instancierez un //CompletionService<String>. CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(executor);

Nous allons dclarer une mthode rsoudre qui va se charger d'excuter les tches travers notre service de terminaison. Pour l'instant, votre mthode devrait ressembler a: Code : Java public static void main(String[] args) { List<Callable<Integer>> taches = new ArrayList<Callable<Integer>>(); Callable<Integer> Callable<Integer> Callable<Integer> Callable<Integer> tache1 tache2 tache3 tache4 = = = = new new new new Task(1); Task(5); Task(10); Task(2);

taches.add(tache1); taches.add(tache2); taches.add(tache3); taches.add(tache4); ExecutorService executor = Executors.newFixedThreadPool(10); } resoudre(executor, taches);

public static void resoudre(final ExecutorService executor, List<Callable<Integer>> taches) { //Le service de terminaison CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(executor); } }

www.siteduzero.com

Le framework Executor

15/17

Le service de terminaison contient plusieurs mthodes, mais nous n'allons en utiliser que deux. La premire SUBMIT, qui comme vous l'aurez srement devin, prend en paramtre un Callable<V> et va lancer votre tche. La seconde est TAKE. La mthode take() va en fait vous permettre d'attendre qu'un rsultat soit prt pour l'utiliser. En d'autres mots, quand une tche s'achve, son rsultat est mis dans une file d'attente. La mthode take() va rcuprer le premier rsultat disponible dans cette file, puis va le supprimer. Ainsi un nouvel appel take() vous renverra le rsultat suivant. Si vous vous souvenez bien, la mthode submit d'un executor renvoie un Future<V>. Et bien celle de CompletionService fait de mme. Commenons par le submit : Code : Java //une liste de Future pour rcuprer les rsultats List<Future<Integer>> futures = new ArrayList<Future<Integer>>(); Integer res = null; try { //On soumet toutes les tches l'executor for(Callable<Integer> t : taches){ futures.add(completionService.submit(t)); } } catch(Exception e){}

De cette faon toutes les tches sont lances dans l'executor via notre service de terminaison. Maintenant se pose le problme de la rcupration des rsultats quand ceux-ci sont disponibles. La premire approche consiste faire une boucle sur la liste de Future<V> et en utilisant la mthode get() rcuprer le rsultat. Cela fonctionne, mais vous ne rcuprez pas le rsultat au moment o il est disponible. V otre appel get() va attendre le rsultat du Future<V> en cours mais d'autres tches pourront tre termines pendant ce temps. Le service de terminaison rgle cette question. Comme dit prcdemment, l'aide de take() vous rcuprerez le premier rsultat disponible. Code : Java for (int i = 0; i < taches.size(); ++i) { try { //On rcupre le premier rsultat disponible //sous la forme d'un Future avec take(). Puis l'appel // get() nous donne le rsultat du Callable. res = completionService.take().get(); if (res != null) { //On affiche le rsultat de la tche System.out.println(res);

} } catch(ExecutionException ignore) {}

Je vous remet le code global pour ceux qui auraient un peu de mal Code : Java public class TestTask {

www.siteduzero.com

Le framework Executor
public static void main(String[] args) { List<Callable<Integer>> taches = new ArrayList<Callable<Integer>>(); Callable<Integer> Callable<Integer> Callable<Integer> Callable<Integer> tache1 tache2 tache3 tache4 = = = = new new new new Task(1); Task(5); Task(10); Task(2);

16/17

taches.add(tache1); taches.add(tache2); taches.add(tache3); taches.add(tache4); ExecutorService executor = Executors.newFixedThreadPool(10); } resoudre(executor, taches);

public static void resoudre(final ExecutorService executor, List<Callable<Integer>> taches){ //Le service de terminaison CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(executor); //une liste de Future pour rcuprer les rsultats List<Future<Integer>> futures = new ArrayList<Future<Integer>>(); Integer res = null; try { //On soumet toutes les tches l'executor for(Callable<Integer> t : taches){ futures.add(completionService.submit(t)); } for (int i = 0; i < taches.size(); ++i) { try { disponible take(). Puis l'appel Callable. //On rcupre le premier rsultat //sous la forme d'un Future avec // get() nous donne le rsultat du res = if (res != null) { //On affiche le resultat de la } System.out.println(res);

completionService.take().get();

tche

} catch(Exception e){ e.printStackTrace(); } finally { executor.shutdown(); }

} catch(ExecutionException ignore) {}

www.siteduzero.com

Le framework Executor
V ous devriez voir affichez les tches ds quelles sont termines. (C'est dire l'affichage "1" "2" "5" "10")

17/17

Ce genre de mthode est trs efficace et faire la mme chose avec des threads ncessite une certaine maitrise. Mais les outils existent, alors autant s'en servir. Le framework Executor permet de s'affranchir avantageusement des threads et des Timers. Il nous permet aussi de disposer de pools de threads efficaces, ce genre d'implmentation n'tant pas vraiment la porte des dbutants. L'organisation des tches dans un service de terminaison permet de manipuler avec une grande facilit les rsultats de tches excutes en parallles. Mais t'a pas parler des verrous et des classes thread-safe ?

Je sais, et pour une bonne raison. En effet en parlant de la thread-safety dans ce cours j'aurais t trs long et vous seriez pass cot du framework Executor. Un conseil donc pour finir :

Privilgiez les Executors aux threads classiques


Lire aussi
Forum Tutoriels News aider moi S.V .P La programmation sur Android Comment extraire des donnes d'un texte en java Addition de plusieurs nombres Nombre de siges identiques la suite Qu'est-ce que le C++ ? Introduction aux sockets time.h et ses fonctions Les Conteneurs de la STL Les identificateurs Deuxime dfi Qt par Developpez.com : une application mobile pour hpital Le concours Prologin 2012 est lanc ! Des nouvelles du langage Ruby ! WebMotion, un nouveau framework web libre en Java Le framework web Play en version 1.1

www.siteduzero.com

Vous aimerez peut-être aussi