Académique Documents
Professionnel Documents
Culture Documents
1
Les Threads
Plan
Introduction
Utilisation basique
Stopper et interrompre un Thread
Synchronisation et verrou
Utilisation avancée.
2
Introduction
Processus
1. est un programme en cours d’exécution.
2 . Chaque processus dispose d’un espace mémoire :
- pour le code
- pour les données
- pour les piles d’exécution (variables locales et adresses de retour des
fonctions)
3. Chaque processus est composé de plusieurs threads.
Threads
1. partagent le même espace de mémoire (code et données), Cela peut
causer des problèmes.
2. dispose chacun d’une pile d’exécution.
3.sont exécutés à tour de rôle sous le contrôle de système d’exploitation
4
Terminologie
5
Threads et Processus avec Java
La machine virtuelle correspond à un processus (créé au
lancement de la machine virtuelle).
Autres threads :
-Le garbage collector ( ramasse miette)
6
Introduction
7
Création
8
Création
Classe anonyme.
Dans les 3 cas les instructions du thread sont définies dans la méthode
run()
9
Quelques fonction de la classe Thread
10
Interface Runnable
MyRunnable implémente l’interface Runnable
11
Interface Runnable
Code Lanceur ( Main par exemple)
Simulation
12
Classe Thread
Classe MyThread héritant de la classe Thread ( Thread implémente
Runnable)
13
Classe Thread
Code Lanceur ( Main par exemple)
Simulation
14
Classe Anonyme
tout est dans le Code Lanceur
15
++/--
Thread :
+ : Ecriture simple.
- : pas d’héritage
Runnable :
+ : Possibilité d’héritage.
Anonyme :
+ : Pratique si le code comporte peu de lignes.
16
Remarques
pas de passage de paramètre au thread via start()
Un thread meurt lorsque sa méthode run() se termine.
Appel de start() une et une seule fois pour chaque thread,
sinon :
18
Suite 2
La création des objets threads pourra se faire, depuis
class Ecrit extends Thread n’importe quel endroit du programme
{ (par exemple depuis une méthode main) de cette
private String texte; façon :
private int nb; Ecrit e1 = new Ecrit ("bonjour", 10) ;
public Ecrit (String texte, int nb) Ecrit e2 = new Ecrit ("bonsoir", 12) ;
{ this.texte = texte ; Ecrit e3 = new Ecrit ( “bonne nuit", 5) ;
this.nb = nb ;
}
public void run () Ces appels ne font cependant rien d’autre que de
{ for (int i=0 ; i<nb ; i++) créer des objets. Le lancement de l’exécution
System.out.print (texte) ; du thread se fait en appelant la méthode start de la
} classe Thread, par exemple :
} e1.start() ; // lance l’exécution du thread e1
Cet appel réalise les opérations nécessaires pour qu’un nouveau thread soit bien pris en
compte à la fois par la "machine virtuelle Java" et par le système d’exploitation, puis lance
l’exécution de la méthode run de l’objet correspondant.
19
« Endormir » un thread
Souvent les Threads sont utilisés pour effectuer des taches qui se répètent
sur des intervalles réguliers.
Cet appel demande que le thread correspondant soit arrêté (on dira "mis en
sommeil“) pour au moins la durée mentionnée. Cette démarche laisse ainsi
la possibilité à d’autres threads de s’exécuter à leur tour.
20
Exemple
class Ecrit extends Thread
{
private String texte; public class TstThr1{
private int nb; public static void main(String args[])
private long attente; {
Ecrit e1 = new Ecrit ("bonjour", 10,5) ;
public Ecrit (String texte, int nb, long attente) Ecrit e2 = new Ecrit ("bonsoir", 12,4) ;
{ this.texte = texte ;this.nb = nb ; Ecrit e3 = new Ecrit ( “bonne nuit",6, 3) ;
this.attente=attente; e1.start();
} e2.start();
e3.start();
public void run () }
{ }
try {
for (int i=0 ; i<nb ; i++)
System.out.print (texte) ;
sleep(attente);
} catch(InterruptedException e){}
}
}
21
Lespublic
threads : un deuxième exemple
class TestThread {
public static void main (String [] args){
Thread ta=new ThreadAfficheLettre(‘a’,100);
Thread tb=new ThreadAfficheLettre(‘b’,100);
System.out.print(« avant »); aaaaaaaaaaab
ta.start(); bbbbbbbbbaaa
tb.start(); aaaaaaaaabbb
System.out.print(« apres »); bbbbbbbbbbaa
} aaaaaaaaabbb
} bbbbbbbbbbaa
class ThreadAfficheLettre extends Thread{ aaaaaaaabbbb
private char lettre; private int time; private cpt=0; bbbbbbbbbbaa
public ThreadAfficheLettre(char lettre,int time) aaaaaaaaabbb
{ this.lettre=lettre; this.time=time;} bbbbbbbbaaaa
/*le travail à effectuer par ce thread*/ aaaaaaabbbbb
Public void run() { bbbbbbbbaaaa
While(cpt<=time) aaaabbbbbbbb
{ bbbbbbaaaaaa
cpt++ aaaaa………...
System.out.print(lettre); }
}
} 22
Les threads : fonctionnement
La méthode start de la classe Thread est appelée pour
lancer effectivement le thread.
Lorsque la méthode sleep est appelée, elle permet de donner la main à l’un
des autres threads, y compris le thread principal.
24
Exemple : Runnable
Nous créeons des objets de type Ecrit par
class Ecrit implements Runnable :
private String texte; Ecrit e1=new Ecrit(“bonjour “,12,3);
private int nb; Mais ces objets ne sont plus des Threads
private long attente; et ne peuvent plus être lancés par la
méthode start.
public Ecrit (String texte, int nb, long attente)
{ this.texte = texte ;this.nb = nb ;
this.attente=attente;
}
Nous devrons tout d’abord créer des
public void run () objets de type Thread en utilisant une
{ forme particulière de constructeur
try {
for (int i=0 ; i<nb ; i++) Thread t1 = new Thread (e1) ;
System.out.print (texte) ;
Thread.sleep(attente); Nous lancerons ensuite classiquement ce
} catch(InterruptedException e){} thread par start :
} t1.start() ;
}
25
Exemple : Runnable
class Ecrit implements Runnable
private String texte;
private int nb; Public class TestRunnable{
private long attente; Public static void main(String [] args)
{
public Ecrit (String texte, int nb, long attente) Ecrit e1=new Ecrit(“bonjour “,12,3);
{ this.texte = texte ;this.nb = nb ; Ecrit e2=new Ecrit(“bonsoir“,10,4);
this.attente=attente; Ecrit e3=new Ecrit(“bonne nuit “,4, 8);
} Thread t1 = new Thread (e1) ;
Thread t2=new Thread(e2);
public void run () Thread t3=new Thread(e3);
{ t1.start() ;
try { t2.start();
for (int i=0 ; i<nb ; i++) t3.start();
System.out.print (texte) ; }
Thread.sleep(attente); }
} catch(InterruptedException e){}
}
}
26
Remarques
vous pouvez doter votre classe Ecrit d’une méthode nommée start
jouant alors un double rôle : création de l’objet de type Thread et
lancement du thread :
27
Runnable: un deuxième exemple
Public class TestRunnable{
public static void main (String [] args){
Runnable ra=new RunnableAfficheLettre(‘a’,100);
Runnable rb=new RunnableAfficheLettre(‘b’,100);
Thread ta=new Thread(ra);
Thread tb=new Thread(rb);
ta.start();
tb.start();
System.out.println("fin du programme");
}
}
Class RunnableAfficheLettre implements Runnable{
private char lettre; private int time; private cpt=0;
public RunnableAfficheLettre (char lettre,int time)
{ this.lettre=lettre; this.time=time;}
/*le travail à effectuer par ce thread*/
Public void run() {
While(cpt<=time) {
cpt++
System.out.println(lettre); }
}
} 28
La méthode join
Public final void join() throws InterruptedException {…}
}
29
Problématique
EX: Réservoir-Banque
30
Exemple
Exemple d’une banque possédant plusieurs comptes.
Nous générons au hasard des transactions qui déplacent de l’argent
entre ces comptes.
31
Exemple
32
Coordination de threads
L’avantage des threads sur les processus est qu’ils appartiennent à un
même programme.
En effet, dans certains cas, il faudra éviter que deux threads puissent
accéder (presque) en même temps au même objet.
34
Synchronized
• Synchronizd (list) {
list.add(“ok“);
} retrait du verrou
Équivalent à :
Java offre un mécanisme basé sur l’objet et sur les méthodes synchronisées
une méthode synchronisée peut appeler la méthode wait de l’objet dont elle
possède le verrou, ce qui a pour effet :
une méthode synchronisée peut appeler la méthode notifyAll d’un objet pour
prévenir tous les threads en attente sur cet objet et leur donner la possibilité de
s’exécuter (le mécanisme utilisé et le thread effectivement sélectionné pourront
dépendre de l’environnement).
38
Synchronisation de threads
Coordination entre threads
Coordination entre threads est géré au sein d’un objet à l'aide de ses méthodes
wait() : le thread est mis en attente infinie jusqu'à ce qu’il soit notifié
notify() : un thread notifie un seul autre thread afin de mettre fin à son attente
39
Exemple
Gestion d’une "réserve “. Il comporte :
Les trois threads sont lancés par main et interrompus lorsque l’utilisateur le
souhaite (en frappant un texte quelconque).
40
public class Synchro3 class ThrAjout extends Thread
{ public static void main (String args[]) {private int vol;
{ Reserve r = new Reserve () ; private Reserve r;
private int delai;
ThrAjout ta1 = new ThrAjout (r, 100, 15) ;
public ThrAjout (Reserve r, int vol, int delai)
ThrAjout ta2 = new ThrAjout (r, 50, 20) ; { this.vol = vol ; this.r = r ; this.delai = delai ;
ThrPuise tp = new ThrPuise (r, 300, 10) ; }
System.out.println ("Suivi de stock --- faire entree pour public void run ()
arreter ") ; { try
ta1.start () ; ta2.start () ; tp.start () ; { while (!interrupted())
Clavier.lireString() ; { r.ajoute (vol) ; sleep (delai) ;
ta1.interrupt () ; ta2.interrupt () ; tp.interrupt () ; }
} }
} catch (InterruptedException e) {}
class Reserve }
}
{private int stock=500;// stock initial=500
public synchronized void puise (int v) throws
InterruptedException
{ if (v <= stock) { System.out.print ("-- on puise " + v) ;
stock -= v ; class ThrPuise extends Thread
System.out.println (" et il reste " + stock ) ; {private int vol;
} private Reserve r;
else { System.out.println ("** stock de " + stock private int delai;
+ " insuffisant pour puiser " + v ) ; public ThrPuise (Reserve r, int vol, int delai)
{ this.vol = vol ; this.r = r ; this.delai = delai ;
wait() ;
}
}
public void run ()
} { try
public synchronized void ajoute (int v) { while (!interrupted())
{ stock += v ; { r.puise (vol) ;
System.out.println ("++ on ajoute " + v sleep (delai) ;
+ " et il y a maintenant " + stock) ; }
notifyAll() ; }
} catch (InterruptedException e) {}
} }
} 41
Résultat :
-- on puise 300 et il reste 0
++ on ajoute 50 et il y a maintenant 50
++ on ajoute 50 et il y a maintenant 50
42
États d’un thread
Au départ, on crée un objet thread. Tant que l’on ne fait rien, il n’a aucune chance d’être
exécuté. L’appel de start rend le thread disponible pour l’exécution. Il est alors considéré
comme prêt.
Il peut être interrompu par l’environnement qui le ramène à l’état prêt ; c’est ce qui se produit
lorsque l’on doit donner la main à un autre thread (sur le même processeur). Cette transition
peut être "programmée" en appelant la méthode yield de la classe Thread.
Il peut être mis "en sommeil" par appel de la méthode sleep. Cet état est différent de prêt car
un thread en sommeil ne peut pas être lancé par l’environnement. Lorsque le temps de
sommeil est écoulé, l’environnement replace le thread dans l’état prêt (il ne sera relancé que
lorsque les circonstances le permettront).
Il peut être mis dans une liste d’attente associée à un objet (appel de wait). Dans ce cas, c’est
l’appel de notifyAll qui le ramènera à l’état prêt.
Il peut lancer une opération d’entrée-sortie et il se trouve alors bloqué tant que l’opération n’est
pas terminée.
• Il peut s’achever.
43
Etats d’un thread
44
Etats d’un thread
45
Etats d’un thread
46