Chapitre
Java Avancé
2
Thread
1
2014 - 2015 © Yousri Kessentini
Thread
les threads sont des processus légers qui s’exécutent en parallèle
mais partagent les données.
Sur un OS évolué, exécution concurrente possible des
processus avec “temps partagé” géré par un scheduler
Java Avancé
Fenêtres Multiples
Calcul en tâche de fond
Animation
Producteur/consommateur
Serveur avec plusieurs clients (web ou autres)
Recherche (base de données, web)
2
2014 - 2015 © Yousri Kessentini
Thread en Java
Java propose deux solutions :
Objet héritant de la classe [Link].
Public class Proc1 extends [Link]{
Public Proc1(){...} //Le constructeur
Java Avancé
...
Public void run(){
... //Ici ce que fait le processus (boucle infinie)
}}
Proc1 p1=new Proc1(); //Création du processus
[Link](); //Démarre le processus et exécute [Link]()
3
2014 - 2015 © Yousri Kessentini
Thread en Java
Objet implémentant l’interface [Link]
Public class Proc2 implements [Link]{
Public Proc2(){...} //Le constructeur
Java Avancé
...
Public void run(){
... //Ici ce que fait le processus (boucle infinie)
}}
Proc2 p=new Proc2();
Thread p2= new Thread (p);
[Link](); //Démarre le processus et exécute [Link]()
4
2014 - 2015 © Yousri Kessentini
Que choisir ?
Hériter de Thread
Pour paralléliser une classe qui n’hérite pas déjà d’une autre
classe (héritage simple) ;
Implémenter Runnable
Java Avancé
Lorsqu’une super-classe est imposée ;
Exemple: Cas des applets
public class MyThreadApplet
extends Applet implements Runnable { . . . }
5
2014 - 2015 © Yousri Kessentini
Exemple
class TPrint1 extends Thread { public class TestThread1 {
String txt; static public void main(String
int attente; args[]) {
public TPrint1(String t, int p) { TPrint1 a = new TPrint1("A",
txt = t; 100);
attente = p; TPrint1 b = new TPrint1("B",
Java Avancé
200);
}
[Link]();
public void run() {
[Link]();
for (int i=0; i<8; i++) {
}
[Link](txt+i+" ");
}
try {
sleep(attente);
}
Résultat de l'exécution :
catch(InterruptedException e)
{};
} A0 B0 A1 B1 A2 A3 B2 A4
} A5 B3 A6 A7 B4 B5 B6 B7
}
6
2014 - 2015 © Yousri Kessentini
Exemple
class TPrint2 implements Runnable { public class TestThread2 {
String txt; static public void main(String args[]) {
int attente; TPrint2 a = new TPrint2("A", 100);
public TPrint2(String t, int p) { TPrint2 b = new TPrint2("B", 200);
txt = t; new Thread(a).start();
attente = p; new Thread(b).start();
Java Avancé
} }
public void run() { }
for (int i=0; i<8; i++) {
[Link](txt+i+" ");
try {
[Link]().sleep(
attente);
} Résultat de l'exécution :
catch(InterruptedException e) {};
}
}
A0 B0 A1 B1 A2 A3 B2 A4
} A5 B3 A6 A7 B4 B5 B6 B7
7
2014 - 2015 © Yousri Kessentini
Java Avancé
Méthodes de la classe Thread
8
2014 - 2015 © Yousri Kessentini
Java Avancé
Gestion des Threads
9
2014 - 2015 © Yousri Kessentini
Ordonnancement du Thread
En général, le thread exécutable avec la plus haute priorité
est activé (running)
Java est priority-preemptive
Si un thread de haute-priorité se réveille, et un thread
de basse priorité s’exécute
Java Avancé
Alors le thread de haute priorité s’exécute
immédiatement
Permet l’exécution à la demande
utilisation efficace du CPU
10
2014 - 2015 © Yousri Kessentini
Synchronisation des threads
start()
Thread Thread
Java Avancé
extends Thread/ implement Runnable extends Thread/ implement Runnable
méthodeA() méthodeA()
méthodeB() méthodeB()
run() run() Attributes
Attention ! 11
2014 - 2015 © Yousri Kessentini
Exemple
thread 1 thread 2
Java Avancé
x = attribute
attribute = attribute + 1
x = x+1
attribute = x
incrément perdu
12
2014 - 2015 © Yousri Kessentini
Solution 1
thread 1
class Xxx { thread 2
Object o = new Object();
Java Avancé
public void methodeB() {
synchronized (o) { // one thread at a time
attribute = attribute + 1;
}
}
13
2014 - 2015 © Yousri Kessentini
Solution 2
thread 1
class Xxx { thread 2
Java Avancé
public synchronized void methodeB() {
attribute = attribute + 1;
}
}
// l’objet unique de protection est l’objet qui contient
methodeB() . Il doit être instancié. Pas d’accès static.
14
2014 - 2015 © Yousri Kessentini
Exemple
class Compte {
private int solde;
synchronized public void depot(int valeur)
{
int nouveauSolde;
Java Avancé
nouveauSolde = solde + valeur;
solde = nouveauSolde ;
}
synchronized public void retirer(int valeur)
{
int nouveauSolde ;
nouveauSolde = solde - valeur;
solde = nouveauSolde ;
}
}
15
2014 - 2015 © Yousri Kessentini
Attente explicite : wait() - notify()
Producteur/Consommateur
Une mémoire tampon est alimentée par un producteur
d’objets et utilisée par un consommateur
On synchronise l’accès à cette mémoire (production et
consommation non simultanées)
Java Avancé
Si le producteur doit déposer un objet alors qu’il en existe
déjà un dans le tampon => blocage ;
Même problème pour un consommateur qui attend le dépôt.
16
2014 - 2015 © Yousri Kessentini
Attente explicite : wait() - notify()
Relachement d’exclusion
L’attente du consommateur ou du producteur se fait par
wait() (exception InterruptedException) qui relâche
l’exclusion ;
Un processus sort de son endormissement (attente) quand
Java Avancé
un autre processus exécute notify() ou notifyAll() (relance
tous les processus en attente) ;
17
2014 - 2015 © Yousri Kessentini
Wait et Notify: Code
consommateur:
synchronized (lock) {
while (!resourceAvailable()) {
[Link]();
Java Avancé
}
consumeResource();
}
Producteur:
produceResource();
synchronized (lock) {
[Link]();
}
18
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupèrer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
19
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupèrer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
20
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupèrer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
21
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupèrer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
22
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupèrer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
23
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupèrer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
24
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupèrer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
25
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupèrer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
26
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupérer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
27
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupérer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
28
2014 - 2015 © Yousri Kessentini
Séquence du Wait/Notify
Objet Lock
1. synchronized(lock){ 3. produceResource()
4. synchronized(lock) {
Java Avancé
2. [Link]();
5. [Link]();
9. consumeResource();
10. } 6.}
7. Récupérer le lock
8. Retour du wait()
Consommateur Producteur
Thread Thread
29
2014 - 2015 © Yousri Kessentini
Exercice
Un producteur produit des objets (int) et les place dans une file
d’attente
Un consommateur prend ce qu’il trouve dans la file
La file d’attente
Java Avancé
on produit et consomme des entiers (int)
la file est limitée à un entier
Définir les classes Produit, Producteur, Consommateur
30
2014 - 2015 © Yousri Kessentini
Solution: Produit
class Produit {
int contenu;
boolean vide;
Java Avancé
Produit() {vide = true;}
void ajoute(int x) {contenu = x; vide = false;}
int retire() {vide = true; return contenu;}
boolean estVide() {return vide;}
}
31
2014 - 2015 © Yousri Kessentini
Solution : Producteur
class Producteur extends Thread {
Produit produit;
Producteur(Produit p) {[Link] = p;}
public void run() {
int ip;
while (true) {
// dort un moment
Java Avancé
try {sleep((int)([Link]() * 1000));}
catch (InterruptedException e) {};
synchronized (produit) {
if (![Link]()) {
try [Link]();
catch (InterruptedException e);
}
ip = (int)([Link]() * 1000);
[Link](ip);
// signale qu’il y a qqch à prendre
[Link]();
}
}}}
32
2014 - 2015 © Yousri Kessentini
Solution : Consommateur
class Consommateur extends Thread {
Produit produit;
Consommateur (Produit p) {[Link] = p;}
public void run() {
int jp;
while (true) {
Java Avancé
try {sleep((int)([Link]() * 1000));}
catch (InterruptedException e) {};
synchronized (produit) {
if ([Link]()) {
try [Link]();
catch (InterruptedException e);
}
jp = [Link]();
[Link]();
}
}}}
33
2014 - 2015 © Yousri Kessentini