Le concept de thread
Un thread (processus léger ou activité) est :
Un fil d'instructions (un chemin d’exécution) à l'intérieur d'un processus
(programme).
une unité d’exécution au sein d’un même processus (ce n’est pas un autre
processus).
Tous les threads d’un même processus partagent la même zone mémoire.
Un thread possède un nom, une priorité, etc.
Un thread s’exécute jusqu’au moment où:
Un thread de plus grande priorité devient exécutable.
Une méthode wait (), yield () ou sleep () est lancée.
Son quota de temps a expiré dans un système préemptif.
La programmation multithreads donne l’illusion de la simultanéité.
De nombreux threads peuvent s'exécuter simultanément dans un
programme (exécution concurrente de threads).
Les ressources allouées à un processus (temps processeur, mémoire)
sont partagées entre les threads qui le composent.
Langage
LangageFortran
Java Les threads en Java 2 2
Le concept de processus
Un processus est une instance en exécution d’un programme
Un processus peut contenir plusieurs threads
Un processus possède au moins un thread (qui exécute le programme
principal, habituellement la fonction main()).
La gestion de l’exécution des processus est assurée par le
système d’exploitation (OS)
Un OS est capable d’exécuter plusieurs processus en même
temps: multi-tasking (Linux, Windows 7, …)
Langage
LangageFortran
Java Les threads en Java 3 3
Différences entre un thread et un processus
Au niveau de la mémoire :
Les sous-processus issus d’un même processus ont leur propre
espace d’adressage et doivent, pour communiquer, utiliser des
moyens de communication spécifiques (tubes..)
Les threads issus d’un même processus partagent la même zone
mémoire (segments de code et de données), ce qui rend très facile
(et périlleux !) la communication entre threads.
Langage
LangageFortran
Java Les threads en Java 4 4
Intérêts des threads en général
Communication très simple grâce aux données partagées
Augmenter la "productivité" d’une application par l'exécution
concurrente de ces threads
Exécuter des traitements en parallèle (gagner du temps)
Maintenir la réactivité d’une application durant une longue tache
d’exécution.
Donner la possibilité d’annulation de taches spéciales
Langage
LangageFortran
Java Les threads en Java 5 5
Threads et Java
En java, un thread est un objet
On le crée et on lui assigne des traitements à faire
La JVM prend en charge la responsabilité d’exécuter le thread
Un thread a plusieurs états
public class Main {
public static void main(String[] args) {
System.out.println("Nom du thread: "+Thread.currentThread().getName());
System.out.println(" Etat du thread: "+Thread.currentThread().getState());
System.out.println(" Id du thread: "+ Thread.currentThread().getId());
}
}
Résultat d’exécution
Langage
LangageFortran
Java Les threads en Java 6 6
Comment créer des Threads en Java?
Un thread java est un objet qui control l’exécution d’un programme.
C’est une instance de la classe Thread
Deux façons pour créer un thread java :
Etendre la classe Thread Implanter l’interface Runnable
class Xxx implements Runnable{
class Xxx extends Thread{ …..
….. }
}
Langage
LangageFortran
Java Les threads en Java 7 7
Comment créer des Threads en Java?
Créer Thread avec Thread ou Runnable?
Créer un Thread avec Runnable.
Si Thread doit être une sous-classe d’une autre classe (une classe
ne peut pas avoir 2 sous-classes: pas d’héritage multiple en java)
Créer un Thread avec Runnable.
pour cacher les variables et méthodes de la classe Thread
Langage
LangageFortran
Java Les threads en Java 8 8
Comment créer des Threads en Java?
Etendre la classe Thread
public class MyThread extends Thread {
public MyThread(String nom) {
super(nom);
}
public void run() {// corps du thread
for (int i=0; i<3; i++)
System.out.println(" je suis le thread : "+getName());
}
public static void main(String args[ ]) {
new MyThread("Premier thread").start();
new MyThread("Deuxieme thread").start();
}
}
je suis le thread : Deuxieme thread
Résultat d’exécution je suis le thread : Premier thread
je suis le thread : Deuxieme thread
je suis le thread : Deuxieme thread
je suis le thread : Premier thread
je suis le thread : Premier thread
Langage
LangageFortran
Java Les threads en Java 9 9
Comment créer des Threads en Java?
Implanter l'interface Runnable
public class MyExecutable implements Runnable {
String nom;
public MyExecutable(String nom) {
this.nom = nom;
}
@Override
public void run() {// corps du thread
for (int i=0; i<3; i++)
System.out.println(" je suis l’executable: "+ nom);
}
public static void main(String args[ ]) {
new Thread(new MyExecutable("Premier executable")).start();
new Thread(new MyExecutable("Deuxieme executable")).start();
}
}
je suis l’executable: Deuxieme executable
Résultat d’exécution je suis l’executable: Premier executable
je suis l’executable: Premier executable
je suis l’executable: Premier executable
je suis l’executable: Deuxieme executable
je suis l’executable: Deuxieme executable
Langage
LangageFortran
Java Les threads en Java 10 10
Méthodes start() et run()
La différence principale entre ces deux méthode est que:
lorsque le programme appelle la méthode start(), un nouveau thread
est créé et lui associé une pile d’exécution et le code à l'intérieur de
la méthode run () est exécuté dans cette pile,
alors que si on appel la méthode run () directement aucun nouveau
thread n’est créé et le code à l'intérieur de run() s’exécutera par le
Thread en cours.
Langage
LangageFortran
Java Les threads en Java 11 11
Différences avec un appel à run()
public class MyThread extends Thread {
public MyThread(String nom) {
super(nom);
}
public void run() {// corps du thread
for (int i=0; i<3; i++)
System.out.println(" je suis le thread : "+getName());
}
public static void main(String args[ ]) {
new MyThread("Premier thread").run(); //start();
new MyThread("Deuxieme thread").run(); //start();
}
}
Résultat d’exécution
je suis le thread : Premier thread
je suis le thread : Premier thread Exécution séquentiel !!
je suis le thread : Premier thread Voir slide 9 pour comparer
je suis le thread : Deuxieme thread
je suis le thread : Deuxieme thread
je suis le thread : Deuxieme thread
Langage
LangageFortran
Java Les threads en Java 12 12
Quelques méthodes de la classe: java.lang.Thread
Méthode Description
start () Rend un thread exécutable en lançant la méthode run ().
sleep (i) Endort le thread pour i millisecondes.
wait ()* Suspend le thread.
notify ()* Place le thread dans un état exécutable.
notifyAll ()* Réveille tous les threads en attente.
yield () Place le thread de l’état « en cours d’exécution » à l’état «
exécutable ».
setPriority (i) Modifie la priorité d’un thread (i est compris entre
MIN_PRIORITY et MAX_PRIORITY).
join() Pour qu'un deuxième thread attende la fin d'exécution d'un
join (long) premier thread, il suffit d'appeler la méthode join sur le
premier thread. Un paramètre de temps (en millisecondes)
peut être spécifié.
* Méthodes héritées de la classe java.lang.Object
Langage
LangageFortran
Java Les threads en Java 13 13
Simulation de comportement (séquentielle): sans Thread
Simuler le comportement d’une personne
manger() (1 secondes ( minutes))
marcher() (2 secondes (minutes))
Les deux traitements se font de manière
séquentielle (3 secondes(minutes) pour manger
et marcher
Modèle 1 Modèle 2
Langage
LangageFortran
Java Les threads en Java 14 14
Simulation de comportement (séquentielle): sans Thread
Résultat
class A { d’exécution
void manger() {
Miette 1
for(int i=1;i<=10;i++) Miette 2
System.out.println(" Miette"+i); Miette 3
Miette 4
} Miette 5
} Miette 6
Miette 7
Miette 8
class B { Miette 9
void marcher() { Miette 10
Pas 1
for(int i=1;i<=10;i++) Pas 2
System.out.println(" Pas "+i); Pas 3
} Pas 4
Pas 5
} Pas 6
Pas 7
Pas 8
public class Main{ Pas 9
Pas 10
public static void main(String[] args) {
A a=new A();
B b=new B();
a.manger();
b.marcher();
}
}
Langage
LangageFortran
Java Les threads en Java 15 15
Simulation de comportement (parallèle??): avecThread
class A extends Thread{ Résultat
void manger() {
for(int i=0;i<10;i++) d’exécution
System.out.println(" Miette "+i);
} Miette 0
public void run() { Miette 1
manger(); Miette 2
} Miette 3
} Miette 4
Pas 0
class B extends Thread{ Miette 5
void marcher() { Pas 1
for(int i=0;i<10;i++) Miette 6
System.out.println(" Pas "+i); Pas 2
} Miette 7
public void run() { Pas 3
marcher(); Pas 4
} Miette 8
} Pas 5
Miette 9
public class Main{ Pas 6
Pas 7
public static void main(String[] args) { Pas 8
A a=new A(); Pas 9
B b=new B();
a.start();
b.start();
}
}
Langage
LangageFortran
Java Les threads en Java 16 16
Simulation de comportement (parallèle): avecThread
class A extends Thread{
void manger() { Résultat d’exécution
for(int i=0;i<10;i++) {
System.out.println("Miette "+i); Miette 0
try { Thread.sleep(1000); }catch(Exception exp) {} Pas 0
} Pas 1
} Miette 1
public void run() { Pas 2
manger(); Miette 2
} Pas 3
} Miette 3
class B extends Thread{ Pas 4
void marcher() { Miette 4
for(int i=0;i<10;i++){ Miette 5
System.out.println("Pas "+i); Pas 5
try { Thread.sleep(1000); }catch(Exception exp) {} Miette 6
} Pas 6
Miette 7
} Pas 7
public void run() { marcher(); } Miette 8
} Pas 8
public class Main{ Miette 9
public static void main(String[] args) {
Pas 9
A a=new A();
B b=new B();
a.start();
b.start();
}
}
Langage Java Les threads en Java 17
Thread et JVM
Deux résultats d’exécution différents
Pas 0 Miette 0
Le thread a besoin de JVM pour Miette 0 Pas 0
s’exécuter Pas 1
Miette 1
Pas 1
Miette 1
Miette 2 Pas 2
Pas 2 Miette 2
À une unité de temps donnée, un seul Miette 3 Pas 3
Pas 3
thread qui s’exécute Miette 4
Miette
Pas 4
3
Pas 4 Miette 4
Miette 5 Miette 5
Pas 5 Pas 5
Quant il s’agit de plusieurs threads Miette
Pas 6
6 Miette
Pas 6
6
qui s’exécutent en parallèle, le JVM Miette
Pas 7
7 Miette
Pas 7
7
décide quel thread s’exécuter pour Miette 8 Miette 8
Pas 8 Pas 8
une unité de temps (Threads Pas 9 Miette 9
Miette 9 Pas 9
scheduler algorithm)
Le développeur ne peut pas prévoir l’ordre d’exécution: se fait
de manière aléatoire par la JVM
Langage
LangageFortran
Java Les threads en Java 18 18
Thread et JVM
Thread scheduler choisit un Thread à exécuter
Exécution d’un thread parmi plusieurs Threads
Chaque thread change d’état entre running et en attente jusqu’à
terminer son traitement
Langage
LangageFortran
Java Les threads en Java 19 19
Cycle de vie et les états d’un Thread
Démarrage
du thread
(start()) wating, blocked, sleeping, dead
Non Prêt à s’exécuter: ne sera jamais choisi par la JVM tant qu’il est dans
cet état
Prêt à s’exécuter (runnable): se trouve dans le pool d’exécution et éligible
à s’exécuter mais le scheduler ne l’a pas encore piqué
Le thtread ne peut entrer à cet état seulement si la méthode start() a été appelée
sur lui
En exécution (running): quand le thread entre dans cet état la JVM
prend en charge l’exécution du code se trouvant dans la méthode run()
Le thread reste dans cette état jusqu’à ce que le scheduler le rend au pool
Langage
LangageFortran
Java Les threads en Java 20 20
Cycle de vie et les états d’un Thread
class A extends Thread{ Résultat d’exécution
void manger() {
for(int i=0;i<10;i++) { je me suis réveillé plus tard!!
System.out.println("Miette "+i); Entrer à l’école
try { Thread.sleep(1000); }catch(Exception exp) {} Commencer le travail
} Miette 0
} Pas 0
public void run() {
Pas 1
manger();
} Miette 1
} Miette 2
class B extends Thread{ Pas 2
void marcher() { Pas 3
for(int i=0;i<10;i++){ Miette 3
System.out.println("Pas "+i);
Miette 4
try { Thread.sleep(1000); }catch(Exception exp) {}
} Pas 4
Pas 5
} Miette 5
public void run() { marcher(); } Pas 6
} Miette 6
public class Main{
Pas 7
public static void main(String[] args) {
System.out.println("je me suis réveillé plus tard!!"); Miette 7
A a=new A(); Pas 8
B b=new B(); Miette 8
a.start(); Pas 9
b.start(); Miette 9
System.out.println("Entrer à l’école");
System.out.println("Commencer le travail");
} Il faut réglé ce problème !!!!
}
Langage
LangageFortran
Java Les threads en Java 21 21
Influencer le cycle de vie et les états d’un Thread
Utilisation de la méthode join() d’un Thread
join()
Utilisé si on souhaite que le thread soit exécuté après l’exécution d’un autre
thread
Utile quand l’exécution d’un thread dépend de l’exécution d’un autre
thread
L’instruction t.joint() bloque le thread COURANT jusqu’à la fin de l’exécution
du thread contrôlé par t
L’instruction t1.joint() est exécutée par un autre thread t2. Cela signifie
que t2 doit attendre la fin de t1 et reprend son exécution.
Langage
LangageFortran
Java Les threads en Java 22 22
Influencer le cycle de vie et les états d’un Thread
Résultat d’exécution
Utilisation de la méthode join() d’un Thread
je me suis réveillé plus tard!!
Pas 0
Miette 0
public class Main{ Miette 1
public static void main(String[] args) {
Pas 1
System.out.println("je me suis réveillé plus tard!!");
A a=new A(); Pas 2
B b=new B(); Miette 2
a.start(); Pas 3
b.start(); Miette 3
try { Miette 4
a.join();
Pas 4
b.join();
}catch(Exception e) {} Miette 5
System.out.println("Entrer à l’école"); Pas 5
System.out.println("Commencer le travail"); Miette 6
} Pas 6
} Miette 7
Pas 7
Miette 8
Pas 8
Miette 9
Pas 9
Entrer à l’école
Commencer le travail
Langage
LangageFortran
Java Les threads en Java 23 23
Influencer le cycle de vie et les états d’un Thread
Résultat d’exécution
Fixer l’ordre de priorité d’un Thread
je me suis réveillé plus tard!!
Miette 0
public class Main{ Pas 0
public static void main(String[] args) { Miette 1
System.out.println("je me suis réveillé plus tard!!"); Miette 2
A a=new A(); Pas 1
B b=new B(); Miette 3
Miette 4
a.setPriority(Thread.MAX_PRIORITY); Miette 5
b.setPriority(Thread.MIN_PRIORITY); Pas 2
Miette 6
a.start(); Miette 7
b.start(); Pas 3
try { Miette 8
a.join(); Miette 9
b.join(); Pas 4
}catch(Exception e) {} Pas 5
System.out.println("Entrer à l’école"); Pas 6
System.out.println("Commencer le travail"); Pas 7
} Pas 8
} Pas 9
Entrer à l’école
Enlever la méthode « sleep() »!!! Commencer le travail
Parfois, deux threads peuvent accéder à une donnée en même
temps: problème!!!!
Langage
LangageFortran
Java Les threads en Java 24 24
Problème de ressource partagée
Dans le cas où il s’agit d’un accès concurrent à une ressource,
des problèmes de synchronisation peuvent se poser,
Java offre la possibilité de gérer ce genre de problème
Exemple de problème
Initialisation: x=2, création de deux threads T1 et T2
Objectif: incrémenter la valeur de x par deux threads T1 et T2
1.T1 : lit la valeur de x (=2)
2. T2 : lit la valeur de x (=2)
3. T1 : calcule x + 1 (x=3)
4. T2 : calcule x + 1 (x=3)
5. T1 : range la valeur calculée dans x (=3)
6. T2 : range la valeur calculée dans x (=3)
x contient 3 au lieu de 4 !
Langage
LangageFortran
Java Les threads en Java 25 25
Synchronisation entre Threads
En programmation parallèle, on appelle section critique, une
partie du code qui ne peut être exécutée en même temps par
plusieurs threads sans risquer de provoquer des anomalies de
fonctionnement
Il faut donc éviter l’exécution simultanée de sections critiques par
plusieurs threads
En Java le mot clé synchronized est utilisé pour synchroniser les
threads et les empêcher d’exécuter en même temps des portions
de code
Plusieurs threads ne peuvent exécuter en même temps du code
synchronisé sur un même objet
La synchronisation est un mécanisme qui coordonne l’accès à
des données commune et à des code critique par des threads
Langage
LangageFortran
Java Les threads en Java 26 26
Synchronisation entre Threads
Identifier les parties critiques de code
Un seul thread à la fois qui doit accéder à ces parties
Java utilise le mécanisme de verrouillage
Si un thread arrive à accéder à un code critique (non verrouillé par
un autre thread) il le verrouille. Ainsi il possède le verrou (lock)
Un seul thread à la fois qui peut avoir le verrou
Tant que un thread ne relâche pas le verrou (lock) sur un objet,
les autres threads ne peuvent pas accéder à ces parties critiques,
Langage
LangageFortran
Java Les threads en Java 27 27
Synchronisation entre Threads
Seulement la méthode entière ou l’une de ces parties qui peuvent
être synchronisée
On ne peut pas synchroniser une classe ou des attributs
Langage
LangageFortran
Java Les threads en Java 28 28
Synchronisation entre Threads
Comment synchroniser?
La syntaxe est la suivante :
... code non protégé ...
synchronized(objet) {
... code protégé ...
}
... code non protégé ...
Le code protégé n'est exécuté que par un seul thread à la fois, tant
qu'il n'a pas terminé le bloc d'instruction.
Durant l'exécution de ce code protégé par un thread, un autre thread ne
peut exécuter celui-ci, mais peut exécuter un autre bloc synchronized si
celui-ci n'utilise pas le même objet et qu'il n'est pas déjà en cours
d'exécution
Langage
LangageFortran
Java Les threads en Java 29 29
Synchronisation entre Threads
Comment synchroniser?
Synchroniser une méthode en sa totalité est le moyen le plus simple
pour assurer qu’un seul thread accède à un code critique
public synchronized void codeProtege() {
... code protégé ...
}
public synchronized void incremente() {
for (int i=0; i<20000;i++) {
contenu++;
System.out.println(getName()+"incremente "+i);
}
Parfois, seulement une partie du code qui a besoin d’être protégée.
Dans ce cas, la partie du code à protéger est synchronisée avec un
objet.
public void codeProtege() {
synchronized(this) {
... code protégé ...
}
public void run() {
}
synchronized (this){
this.contenu++;
System.out.println(getName()+"incremente ");
}
}
Langage
LangageFortran
Java Les threads en Java 30 30
Synchronisation entre Threads
Résumé
Tant que t exécute du code synchronisé sur un objet o,
les autres threads ne peuvent exécuter du code
synchronisé sur ce même objet o (le même code, ou
n’importe quel autre code synchronisé sur o) ; ils sont
mis en attente
Lorsque t quitte le code synchronisé ou se met en attente
par o.wait(), un des threads en attente peut commencer à
exécuter le code synchronisé
Les autres threads en attente auront la main à tour de rôle (si
tout se passe bien...)
Langage
LangageFortran
Java Les threads en Java 31 31
Exemple sans synchronisation sur une variable de classe
class Compteur extends Thread{
private static int valeur=0 ;
void incremente (){
for(int i=0;i<1000;i++) {
Résultat d’exécution
valeur += 1 ;
try { Thread.sleep(100); }catch(Exception exp) {}
}
}
static int Combien () { return valeur ; }
public void run() { incremente(); }
}
public class MainCompteur{
public static void main(String[] args) {
Compteur c1=new Compteur();
Compteur c2=new Compteur();
c1.setName("-compteur 1-"); c2.setName("-compteur 2-");
c1.start(); c2.start();
try { c1.join(); c2.join(); }catch(Exception e) {}
System.out.println("Total:"+Compteur.Combien());
}
}
Les objets de classe Compteur peuvent accéder simultanément en même
temps à la variable valeur.
Langage
LangageFortran
Java Les threads en Java 32 32
Exemple de synchronisation sur une variable de classe
class Compteur extends Thread{
private static int valeur=0 ;
void synchronized incremente (){
for(int i=0;i<1000;i++) {
Résultat d’exécution
valeur += 1 ;
try { Thread.sleep(100); }catch(Exception exp) {}
}
}
static int Combien () { return valeur ; }
public void run() { incremente(); }
}
public class MainCompteur{
public static void main(String[] args) {
Compteur c1=new Compteur();
Compteur c2=new Compteur();
c1.setName("-compteur 1-"); c2.setName("-compteur 2-");
c1.start(); c2.start();
try { c1.join(); c2.join(); }catch(Exception e) {}
System.out.println("Total:"+Compteur.Combien());
}
}
public final Class getClass(): renvoie la classe de l’objet.
Tous les objets de classe Compteur seront bloqués dans la méthode
incremente().
Langage
LangageFortran
Java Les threads en Java 33 33