You are on page 1of 15
Mastel ASR\RESYD Programmation Distribuée 2017-2018 Université A.Mira de Béjain Faculté des Sciences Exactes Département d"Tnformatique Les Threads en Java 1, Définition En Java, un thread est un objet d’une classe qui dispose d’une méthode nommée run qui sera exécutée lorsque le thread sera démarré. 2. Création Tl existe deux fagons pour créer un thread en Java. L’une consiste a instancier une classe dérivée de la classe Thread, l'autre repose sur I’instanciation d’une classe spéciale, appelée Runnable. Exemple: Premigre méthode Deuxiéme méthode Public class WyThroad extends public void run) ( for (int i=1; i<-L0; i Systen.out.printin (i); 1 Public class MyRunnab public static void main(String inplenents Runnable Tal unnable tl = new MyRunnab) public static void main(Strin MyPhread ¢ = new MyThread(); public void run testart 07 for void start (): la JVM appelle la méthode run() systen.ot du thread*/ ) } Remarques = Les opérations que vous souhaitez effectuer dans une autre pile d'exécution sont a placer dans la méthode run), quiil s‘agisse d'une classe héritant de Thread ou d'une implémentation de Runnable. - Un programme comporte toujours au moins un thread dit "thread principal" correspondant tout simplement 4 la méthode main. java.lang. Runnable effet, on peut implémenter autant d'interfaces que lon souhaite. ‘Avantages Tnconvénients extends Chaque thread @ ses données [On ne peut plus hériter dune | java.lang.Thread qui lui sont propres autre classe Implements Lihéritage reste possible. En | Les attributs de votre classe sont partagés pour tous les threads qui y sont basés. Dans certains cas, il peut s'avérer gue cela soit un atout. 3. La classe Thread La classe Thread est définie dans le package java. ang. Elle implémente l'interface Runnable. 3.1. Construeteurs La classe Thread peut posséder plusieurs constructeurs : un constructeur par défaut et plusieurs autres public Thread(); // crée un nouveau Thread dont le nom est généré automatiquement (aléatoirement), ‘public Thread(Runnable target); // target est le nom de T'objet dont la méthode run est utilisée pour lancer le Thread. «public Thread(Runnable target, String name); // on précise l'objet et le nom du Thread. «public Thread(String name); // on précise le nom du Thread 3.2. Méthodes La classe Thread fournit des méthodes pour gérer les objets Thread : les créer, changer leur priorité définie entre un minimum et un maximum avec une valeur moyenne par défaut, On peut attribuer un nom & un thread, le démarrer, ’interrompre, le détruire, le mettre en attente pendant un nombre de millisecondes, etc. ‘static int MAX_PRIORITY : priorité maximale. « static int MIN_PRIORITY : priorité minimale * static int NORM_PRIORITY : priorité par défaut ‘void setName (String) : définit le nom du thread. ‘String getName (): fournit le nom du thread. ‘* int getPriority () : fournit la priorité du thread, ‘void setPriority (int) : change la priorité. + static Thread currentThread () : fournit une référence sur le thread courant. ‘static void sleep (long n) : le processus est suspendu pour n millisecondes, ‘static int activeCount : nombre de threads du groupe. ‘static int enumerate (Thread_] tabThread) : copie dans le tableau les références des threads actfs. ‘* void start () : la JVM appelle la méthode run() du thread. # run (): appel de la méthode run() de lobjet. + suspend () : suspend le thread. ‘resume (): Ie thread redevient actif. ‘+ void destroy () : détruit le thread, ‘void join () : attend la fin du thread. String toString () : fournit certaines des caractéristiques du thread. Ete Cours PDJ 2017/2018 2 Dr.N. BATTAT 4, L'ordonnancement des threads Llordre d'exécution est souvent aléatoire, car Java utilise un ordonnanceur. Vous devez savoir que si vous utilisez plusieurs threads dans une application, ceux-ci ne s'exécutent pas toujours en méme temps. fait, 'ordonnanceur gére les threads de fagon aléatoire : il va en faire tourner un pendant un. certain temps, puis un autre, puis revenir au premier, etc., jusqu’a ce qu'ils soient terminés. Lorsque Yordonnanceur passe d'un thread 4 un autre, le thread interrompu est mis en sommeil tandis que l'autre est en éveil, L’ordonnancement dépend en fait aussi bien de l'implémentation de la JVM que du systéme exploitation sous-jacent. II y a deux modéles principaux concernant la JVM, Dans le modéle "green thread", c'est la JVM qui implémente l'ordonnancement des threads qui lui sont associés. Dans le modéle "threads natifs", c'est le systéme exploitation hte de la JVM qui effectue 'ordonnancement des threads JAVA. Cours PDJ 2017/2018 3 Dr.N, BATTAT 5. Sommeil d'un thread « static void sleep (long n) : le processus est suspendu pour. Cet appel demande que le Thread correspondant soit arrété (on dira "mis en sommeil") pour au moins la durée mentionnée (n millisecondes). Cette démarche laisse ainsi la possibilité 4 d’autres threads de s’exécuter a leur tour. La méthode sleep est susceptible de générer une exception de type InterruptedException Exemple : Public class TSeinel { public static void main (String args{]) { Berit el = new Berit ("bonjour ", 10, 5) Ecrit 2 = new Ecrit e", 12, 10) ¢ 23 = new Ecrit 15); el.start() rt () e3.start() ; } ) class Ecrit extends Thread { public Ecrit (String texte, int nb, long atte: texte ; this.nb = nb; attente ; , public void run () ( try { for (int i-0 7 icnb 7 itt) { System.out.print (texte) ; sleep (attente) ; , } catch uptedException e) {} // Impose par sleep } private String texte ; private int nb; private long attente ; , Le résultat de Pexécution = bonjour b bonjour b onjour bonjour b bonjour bonjour bonsoir b onjour bonsoir b bonjour b bonsoir b onsoir Cours PDJ 2017/2018 3 Dr.N, BATTAT 6. Priorités des threads La méthode sleep() permet d'endormir un Thread au profit d'un autre. Il existe un autre moyen de gérer le passage du contréle d'un Thread & un autre: & chaque Thread de Java est associée une priorité c'est & dire une valeur numérique qui permet de comparer l'importance de deux Threads et de donner une préférence d'exécution & lun ou & l'autre. «static int MAX_PRIORITY: priorité maximale. «static int MIN_PRIORITY: priorité minimale. «static int NORM_PRIORITY : priorité par défaut. int getPriority () : fournit la priorité du thread. «void setPriority (int) : change la priorité, Exemple : public class TestThreadi0 ( public static void main(string{] args) { ystem,out.printin("Thread.MIN_ PRIORITY = " + Thread.MIN_PRIORTTY) ; system. out.printin("Thread.NORW PRIORITY = " + Thread. NORM , ystem.out.printin("Thread.MAX_ PRIORITY = " + Thread.MAX_ PRIORITY) ; , 1 Thread Thre Thread Le résultat de Pexéeution: MIN_PRIORITY = 1 NORM_PRIORITY = MAX PRIORITY = 10 Cours PDJ 2017/2018 5 Dr.N, BATTAT Lorsqu'un Thread est créé, il hérite de la priorité du Thread qui le erée. Cette priorité peut étre modifige en utilisant la méthode setPriority(int) en donnant une valeur entre MIN_PRIORITY et MAX_PRIORITY (constantes définies dans la classe Thread). Pour des Thread candidats a I'exécution ayant la méme priorité, JAVA fait tourer le droit d'exécution d'un Thread a l'autre dés que ce dr est libéré et condition quil n'y ait pas un Thread de priorité supérieure. La priorité est principalement utilisée pour gérer 'efficacité d'une application Exemple : public class Ant nb; public PrintNb (int nb) { this.nb = nb; } public void run() ntNb implements Aunnableq System. out.printla(); for (int i=0;i<10;i#+) system. out.print (nb); , } public class Nonbres { public static void main(string{] args 1( Thread nbl,nb2, nb3; nbi= new Thread (new PrintNb(1)); nbl.start (); bl. sey (Thread. MN PRIORITY); nb?" new Thread(new PrintNb(2)); nb2.start (); nb2.se} (Thread. Max PRIORITY) ; no3~ new Thread (new PrintNb(3)); np3.start ()7 jority ( Thread. tiokit , ) Le résultat d’exécution : 2222222222 3333333333 qiiliiiiin Cours PDJ 2017/2018 6 Dr.N, BATTAT Un Thread donné peut, & tout moment, renoncer a son droit d'exécution en appelant la méthode yield(). Contrairement sleep(long), ce renoncement n'est pas une mise en sommeil pour une durée fixée au profit de tous les Threads, mais seulement un passage temporaire du contrdle aux autres Threads de méme priorité, Notons que yield() n'émet pas d'exceptions, nous n'avons done pas beso’ de lentourer d'une close wry & catch. Exemple : Glass Vielathread extends Thread public void run() { for (int count = 0; count < 4; co! system. ovt.print yield() n( count + "Pron: "= getName() ); class TestYield public static void main( Yieldthread first YieldThread Cours PDJ 2017/2018 4 Dr. N, BATTAT 7. Interruption d’un thread Les threads s'achevaient tout naturellement avec la fin de "exécution de leur méthode run (qui se produisait aprés un nombre déterminé d’appels de sleep). Dans certains cas, on peut avoir besoin interrompre prématurément un thread depuis un autre thread. Ce besoin peut devenir fondamental dans le cas de ce que nous nommerons des "*hreads infinis", c’est-d-dire dans lesquels la méthode run n’a pas de fin programmée; ce pourrait étre le cas d’un thread de surveillance d’appels dans un serveur Web. Java dispose d’un mécanisme permettant 4 un thread d’en interrompre un autre. La méthode interrupt de la classe Thread demande a l’environnement de positionner un indicateur signalant une demande d’arrét du thread concemé. Par ailleurs, dans un thread, il est possible de connaitre I’état de cet indicateur & ’aide de la méthode statique interrupted (il existe également isInterrupted). Ce schéma récapitule la situation : Thread 1 Thread 2 nommé t tinterrupt() ; // positionne un indicateur dans t if (interrupted) foe return ; // fin du thread } Notez bien que l’arrét effectif du thread 1 reste sous sa propre responsabilité. Rien n’empéche (hormis le bon sens) de faire autre chose que return, voire méme d’ignorer cette demande d’arrét. D’autte part, il est nécessaire que le test de lindicateur se fasse réguligrement dans la méthode run et non simplement au début de son exécution. Cours PDJ 2017/2018 8g Dr.N, BATTAT 8. Coordination de threads Dans certains cas, il faudra éviter que deux threads puis ent accéder (presque) en méme temps au méme objet. Ou encore, un thread devra attendre qu’un autre ait achevé un certain travail sur un objet avant de pouvoir lui-méme poursuivre son exécution, Le premier probléme est réglé par l'emploi de méthodes mutuellement exclusives qu’on appelle souvent, un peu abusivement, "méthodes synchronisées", en faisant référence a la fagon de les déclarer avec le mot-clé synchronized. A un instant donné, une seule méthode ainsi déclarée peut étre appelée pour un objet donné. Exemple : Public class Compte { private int solde = 0; public synchronized void ajouter(int somme) { solde sprint (" ajo System.o public synchronized void retirer(int sone) { solde -= somme; em. out .print (" re " + somme); public synchronized void solde += somme; perationNulle(int some) sprint (" ajou somme) : eprint (" re " + some); public synchronized int getSolde() { return solde; ’ public class Operation extends Thread private Compte compte; public Operation super (non) ; this.compte = compte; ng nom, Compte compte) { public void while (true) int i= (int) (Math.x: String nom = getNane(); system. out.print (nom) ; 0 compte operationMulle (i) ; int solde = compte.getSolde(); system. out.peint (nom) ; if (solde != 0) nom + ":*¥solde=" Cours PDJ 2017/2018 9 Dr. N. BATTAT public static void main (strii Compte compte for (int i new Compte (); A < 207 dn) = new operation("™ + (char) (1A' + i), compte); Cours PDJ 2017/2018 10 Dr. N. BATTAT Le second probléme sera réglé par des mécanismes d’attente et de notification mis en ceuvre a Paide des méthodes wait et notty Remarque : notifyAll): ressemble a notify avec la différence qu'il réveille tous les threads qui était en attente au moment de son exéc * Tri d'un tableau d'e: * Utilisation de wait() et de join() / public class Trieur extends Thread private int{) ty // tableau a trier private int debut, fin; // tranche de ce tableau qu'il faut trier private Trieur parent; // tread Trieur qui a lancé ce (this) private int nbNotify = 0; // Nombre de notifys envoyés 4 (this) Trier public Trieur(int{] this (null, t, 0, public Trieur(Trieur parent, int{] t, int debut, int fin) this.parent rent; this.t = ty this.debut = debut; this.fin = fin; start(); public synchronized void notifier() { // Notifie tous les threads en attente sur "ce" (this) // Attention, quand le message sera envoyé au parent (dans run()), // on incrémentera la variable nbNotify du par t (qui sera le // implicite) et on notifiera le parent. // On peut aussi ne pas utiliser de méthode mais dans ce cas, L fa // écrire parent.nbNotifyt+; parent.notifyAll(); dans un bloc // synchronisé sur parent placé dans la méthode run. public void run() { if (fin - debut < 2) { if (t{debut] > t[fin}) { echanger (debut, fin); Cours PDJ 2017/2018 u Dr. N. BATTAT ? ) int milieu = debut + (fin - debut) / 2; trieurl = new Trieur(this, t, debut, milieu); ieur2 = new Trieur(this, t, milieu + 1, fin); / attend les 2 threads synchronized(this) { ue 2 notifications n'ont pas été recues (1 par // trieur "fils"), on attend. while (nbNotify < 2) { wait): ) ) catch (InterruptedException e) {} } iFusion (debut, fin); ) if (pare null) { parent.notifier(); // Ltattend ) yee * Echanger tli] et tli private void echanger(int i, int 3) { int valeur = tli]; tli] = tty) t{j] = valeur; ye * Fusionne 2 tranches déja triées du tableau t. * = lére tranche : de debut a milieu * = 2ame tranche : de milieu + 1 a fin * @param milieu indique le dernier indice de la 1ére tranche private void trifusion(int debut, int fin) { // tableau ob va aller la fusion ] tFusion = new int[fin - debu milieu = (debut + fin) / 2 // Indices des éléments & comparer 2 = milieu + 1 // indice de 1 iFusion = 0; le (il <= milieu &&@ i2 <= fin) { (eli) < tli2n ¢ he prochaine case du tableau tFusion A remplir tFusion[iFusion++] = tlilt+l; ) else { tFusion[iFusion++] = t{i2++]; ) Cours PDJ 2017/2018 12 Dr. N. BATTAT // la 2éme tranche for (int i= ily i ‘Fusion |iFusion++ ) } // Copie tFusion dans t for (int i= 0, j = debut; i < tjtt] = tFusion[it+]; } iag(] public static void main(s (1 t = {5, 8 3, 2, 7, 10, eur trie new Trieur(t}; yf rieur.join(); , ch (Interruptedzxception e) i 10; ins) { out.printIn("" 4 i); Cours PDJ 2017/2018 15 Dr. N. BATTAT

You might also like