les threads

22
LES THREADS Macodou Diouf (Formateur en Technologie Objet) JAVA AVANCE 1

Upload: akpamagbo

Post on 21-Oct-2015

45 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Les Threads

1

LES THREADS

Macodou Diouf

(Formateur en Technologie Objet)

JAVA AVANCE

Page 2: Les Threads

2

PLAN INTRODUCTION EXEMPLE INTERFACE RUNNABLE INTERRUPTION D’UN THREAD

1. Démarche usuelle d’interruption par un autre thread2. Threads démos et arrêt brutal

COORDINATION DE THREADS1. Méthodes synchronisées2. Exemple3. Notion de verrou4. L’instruction synchronized5. Interblocage6. Attente et notification

ETATS D’UN THREAD PRIORITES DES THREADS

Page 3: Les Threads

3

INTRODUCTION

Machines actuels qu’elles soient monoprocesseur ou multiprocesseur, permettent d’exécuter plus ou moins simultanément plusieurs tâches ou processus.

Sur les machines monoprocesseur, la simultanéité n’est qu’une illusion.

Grace aux threads la multiprogrammation est possible en Java. Un programme Java est formé de plusieurs threads qui

communiquent entre eux et partagent des données. Nous allons voir les deux façons de créer des threads:

Dériver de la classe Thread Implémenter l’interface Runnable

Puis nous verrons comment interrompre un thread depuis un autre thread. Nous apprendrons ensuite à coordonner les actions de plusieurs threads. Ensuite nous passerons en revue les différents états d’un thread. Enfin nous verrons comment agir sur la priorité d’un thread.

Page 4: Les Threads

4

EXEMPLE

Un programme qui va lancer trois threads simple, chacun d’eux se contentant d’afficher un certain nombre de fois un texte donné, à savoir : 10 fois « Bonjour » pour le premier thread 12 fois « Bonsoir » pour le deuxième thread 5 fois un changement de ligne pour le troisième thread

Un thread objet d’une classe disposant d’une méthode run qui sera exécuté lorsque le thread sera démarré

class Ecrit extends Thread{public Ecrit(String texte, int nb)

{this.texte = texte ;this.nb = nb ;}

public void run (){for ( int i = 0 ; i < nb ; i++ )System.out.println(texte) ;}

}

Page 5: Les Threads

5

EXEMPLE

La création des objets threads pourra se faire de la manière suivante :

Ensuite on appelle la méthode start de la classe Thread pour le lancement de l’exécution du thread.

Cette instruction réalise toutes les opération nécessaire pour qu’un nouveau thread puisse être prise en compte à la fois par le JVM et le SE, puis lance l’exécution de la méthode run.

Pour permettre à nos threads de s’exécutent en apparente simultanéité, nous ferons appel à la méthode sleep(t) où t correspond au nombre de millisecondes que le thread sera arrêté (mis en sommeil).

La méthode sleep est susceptible de générer une exception de type InterruptedException.

Ecrit e1 = new Ecrit(« Bonjour », 10);Ecrit e2 = new Ecrit(« Bonsoir », 12);Ecrit e3 = new Ecrit(« \n », 5);

e1.start(); // lance l’exécution du thread e1

Page 6: Les Threads

6

EXEMPLE

Nous allons prévoir un temps de sommeil pour chaque thread.

class Ecrit extends Thread{private String texte; private int nb; private long attente;

public Ecrit(String texte, int nb, long attente){this.texte = texte ;this.nb = nb ;this.attente = attente ;}

public void run (){

try {for ( int i = 0 ; i < nb ; i++ ){

System.out.println(texte) ;sleep(attente) ;

}}catch (InterruptedException e){ }

}}

Page 7: Les Threads

7

EXEMPLE

Remarques

Un programme Java comporte au moins un thread dit « thread principal » correspondant à la méthode main.

L’appel de la méthode sleep permet de donner la main à l’un des autres threads.

L’appel direct de la méthode run de nos objets thread, n’empêche pas notre programme de fonctionner mais on n’aurai plus affaire à trois threads différents.

La méthode start ne peut être appelé qu’une seule fois pour un objet thread donné. Sinon on obtient une exception IllegalThreadStateException.

La méthode sleep est une méthode static de la classe Thread qui met en sommeil le thread en cours d’exécution.

Si nous prévoyons pas d’appel de sleep dans notre méthode run, le programme fonctionnera encore mais son comportement dépendra de l’environnement.

Page 8: Les Threads

8

INTERFACE RUNNABLE

Nous venons de voir une façon très simple de créer des threads à partir de la classe Thread.

Cette méthode présente une lacune puisque les objets ne peuvent pas dérivés d’autre chose que de Thread ( Java ne gère pas l’héritage multiple).

La deuxième manière de créer des threads est d’implémenter l’interface Runnable, laquelle comporte une seule méthode nommée run.

class Ecrit implements Runnable{

public Ecrit (String texte, int nb, long attente){

// mêmes instructions que précedemment}public void run() {

// même contenu que precedemment// en n’oubliant pas que la methode sleep est static

}}

Page 9: Les Threads

9

INTERFACE RUNNABLE

Nous créerons des objets de type Ecrit, de la manière suivante :

L’objet e1 n’est plus un thread et ne peut plus être lancer par la méthode start.

Nous devons donc créer un objet de type Thread et le lancer avec la méthode start.

Exercice d’application :

Transformer l’exemple précèdent, en utilisant la deuxième méthode.

Ecrit e1 = new Ecrit(« Bonjour », 10, 5) ;

Thread t1 = new Thread(e1) ;t1.start() ;

Page 10: Les Threads

10

INTERFACE RUNNABLE

Remarques Dans la pratique, la classe permettant de créer les objets destinés à

être transmis au constructeur de la classe Thread dérivera d’une autre classe (ce qui n’est pas encore le cas).

Nous allons doter de notre classe Ecrit une méthode nommée start jouant alors un double rôle : Création de l’objet de type Thread Lancement du Thread

class Ecrit implements Runnable{public Ecrit(String texte, int nb, long attente){

// constructeur inchangé}public void start (){

Thread t = new Thread (this) ;t.start() ;

}public void run (){

//methode inchangée}……

}

Page 11: Les Threads

11

INTERRUPTION D’UN THREAD

Démarche usuelle d’interruption par un autre threadJusqu’ici les thread s’achevaient tout naturellement avec la fin de l’exécution de leur méthode run.

Dans le cas où la méthode run n’a pas de fin de programme « threads infinis », nous aurons besoin d’interrompre prématurément un thread.

La méthode interrupt de la classe Thread demande à l’environnement de positionner un indicateur signalant une demande d’arrêt du thread concerné.

La méthode static interrupted permet de connaitre l’état de l’indicateur.

Thread 1 Thread 2 nommé t

run (){t.interrupt () ;

….if( interrupted){….return ;}

}

Page 12: Les Threads

12

INTERRUPTION D’UN THREAD

Threads démons et arrêt brutalJusqu’ici, nous avons considéré qu’un programme se termine lorsque le dernier thread est arrêté. En réalité, il existe deux catégories de threads:• Les threads utilisateurs• Les threads démons

Si dans un programme les seuls threads en cours d’exécution sont des démons, le programme est arrêté brutalement.

La méthode System.exit met fin à un programme et provoque, elle-aussi l’arrêt brutal de tous les threads en cours.

La méthode destroy, appliqué à un thread, en provoque également l’arrêt brutal.

Pour faire d’un thread un démon, on appelle la méthode setDaemon (true) avant d’appeler la méthode start.

Page 13: Les Threads

13

COORDINATION DE THREADS

Contrairement aux processus, les threads appartiennent au même programme. Ils peuvent également partager les mêmes objets.

Il faudra donc éviter que deux threads puissent accéder presque en même temps au même objet.

Un thread devra donc 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éthode mutuellement exclusif : synchronized.

Le second problème sera réglé par le mécanisme d’attente et de notification mis en œuvre à l’aide des méthodes wait et notify.

Page 14: Les Threads

14

COORDINATION DE THREADS

Méthodes synchroniséesVoici deux treads qui répètent indéfiniment les taches suivantes:

Thread 1 : incrémentation d’un nombre et calcul de son carré

Thread 2 : Affichage du nombre et de son carré

Si Thread 1 se trouve interrompu entre l’incrémentation et le calcul de carré, le second risque d’afficher le nouveau nombre et l’ancien carré.

Pour pallier cette difficulté, Java permet de déclarer des méthodes 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é.

Page 15: Les Threads

15

COORDINATION DE THREADS

Exemple

class Nombre{private int n = 0, carre ;public synchronize void calcul (){n++;carre = n * n ;}public synchronize void affiche(){System.out.println(n + « a pour carre » + carre) ;}}

Page 16: Les Threads

16

COORDINATION DE THREADS

Notion de verrouA un instant donné, une seule méthode synchronisée peut donc accéder à un objet donné.

Pour chaque objet dotant au moins d’une méthode synchronisée, l’environnement gère un verrou unique permettant l’accès à l’objet.

Le verrou est attribué à la méthode synchronisée appelé pour l’objet et il est restitué à la sortie de le méthode. Tant que le verrou n’est pas restitué, aucune autre méthode synchronisée ne peut le recevoir (les méthodes non synchronisées peuvent quant à elles, accéder à tout moment à l’objet).

Page 17: Les Threads

17

COORDINATION DE THREADS

L’instruction synchronizedUne méthode synchronisée acquiert donc le verrou sur l’objet qui l’a appelée (implicitement) pour toute la durée de son exécution.

L’utilisation d’une méthode synchronisée comporte deux contraintes:• L’objet concerné (celui sur lequel elle acquiert le verrou) est

nécessairement celui qui l’a appelée.• L’objet est verrouillé pour toute la durée de l’exécution de la méthode.

L’instruction synchronized permet d’acquérir un verrou sur un objet quelconque pour une durée limitée à l’exécution d’un simple bloc.

synchronized (objet){// instruction}

Page 18: Les Threads

18

COORDINATION DE THREADS

InterblocageL’utilisation des verrou sur des objets peut conduire à une situation de blocage « étreinte mortelle » qui peut se définir ainsi :• Le thread t1 possède un verrou de l’objet o1 et il attend le verrou de

l’objet o2• Le thread t2 possède un verrou de l’objet o2 et il attend le verrou de

l’objet o1

Ce problème est résolu grâce à l’ordonnancement des ressources qui consiste à numéroter les verrous dans un certain ordre et imposer aux threads de demander les verrous suivant cet ordre.

Page 19: Les Threads

19

COORDINATION DE THREADS

Attente et notificationPour coordonner l’exécution de threads, Java offre une mécanisme basé sur l’objet et sur le méthodes synchronisées.

• Une méthode synchronisée peut appelé la méthode wait de l’objet dont elle possède le verrou, ce qui a pour effet:- de rendre le verrou à l’environnement qui pourra, le cas échéant,

l’attribuer à une autre méthode synchronisée- de mettre « en attente » le thread correspondant; plusieurs threads

peuvent être en attente sur un même objet; tant qu’un thread est en attente l’environnement ne lui donne pas la main.

• Une méthode synchronisée peut appeler la méthode notifyAll d’un objet pour prévenir tous les thrads en attente sur cet objet et leur donner la possibilité de s’exécuter.

Page 20: Les Threads

20

ETATS D’UN THREAD

Nous allons voir les différents « états » dans lesquels peut se trouver un thread et sur les actions qui le font passer d’un état à un autre.

Au départ, on crée un objet Thread. L’appel de start rend le thread disponible pour l’exécution « prêt ». L’environnement peut faire passer un thread de l’état prêt à l’état « en cours d’exécution ».

Un thread en cours d’exécution peut subir différentes actions : Interrompu par l’environnement qui le ramène à l’état prêt Mis « en sommeil » par appel de la méthode sleep Mis dans une liste d’attente associé à un objet (appel de wait) Lancer une opération d’E/S et il se trouve alors bloqué tant que l’opération

d’E/S n’est pas terminée.

Page 21: Les Threads

21

ETATS D’UN THREAD

start

désactivation activation

E/S terminé

Fin méthode run

sleep wait lancement E/S

Temps de sommeil notifyAll

écoulé

objet créé

prêt

en cours d’exécution

morten

sommeil

en attente de

notification

Bloqué en E/S

Page 22: Les Threads

22

PRIORITES DES THREADS

Par défaut tous les threads ont la même priorité. Il es possible de modifier la priorité des threads à l’aide de la méthode setPriority à laquelle on fournit en argument une valeur entière comprise entre 1 et 10.

La priorité d’un thread est exploitée par l’environnement de la manière suivante : Il choisit parmi ceux qui sont l’état prêt celui de plus haut priorité; s’il y’a

plusieurs candidats le choix dépendra de l’environnement Si un thread plus prioritaire que le thread encours d’exécution dévient

prêt, on lui donne la main (l’autre thread passe à l’état prêt).

D’une manière générale, il est déconseillé d’agir sur les priorités des threads dans des programmes qui se veulent portables.