Java Avance
Gestion de processus
Emmanuel ADAM
Université Polytechnique des Hauts-De-France
UPHF/INSA HdF
E. ADAM UPHF Java Avance UPHF/INSA HdF 1 / 42
Plan
1 Présentation
2 Création de processus
3 Transformation en processus
4 Processus et notation lambda
5 Groupe de processus
6 Planification de processus
7 Synchronisation
Principes de la synchronisation
Synchronisation de méthode
Mise en veille et Réveil de processus
8 Exemple type : les producteur et les
consommateurs
Présentation
Codes
9 Volatilité
10 Bloc synchronisé
11 Communication entre processus
E. ADAM UPHF Java Avance UPHF/INSA HdF 2 / 42
Présentation
Processus
Présentation
Un processus est un code qui s’exécute “en parallèle”
c’est-à-dire dont l’exécution n’est pas bloquante pour le reste
du programme
Exemple d’utilisation :
Longs calculs lancés en tâche de fond, permettant de lancer
d’autres calculs
L’interaction avec l’utilisateurs (les fenêtres sont des processus)
Le garbage collector (ramasse miettes) est un processus
E. ADAM UPHF Java Avance UPHF/INSA HdF 3 / 42
Création de processus
Création de processus
classe Thread
Etendre la classe Thread permet de créer un processus
Le comportement principal du processus est à définir dans la
méthode public void run()
La méthode run() est constituée généralement d’une boucle
longue
longs calculs
attente de données (de l’interface graphique, du réseau, . . . )
Elle est appelée par la méthode start()
E. ADAM UPHF Java Avance UPHF/INSA HdF 4 / 42
Création de processus
Exemple de Thread (1/2)
Le programme principal est le processus principal
Exemple de création d’une classe de processus qui affiche son
nom en boucle.
c l a s s UneTache e x t e n d s Thread
{
i n t nbRuns=0 ;
UneTache ( S t r i n g nom ) { s u p e r ( nom ) ; }
// r e m a r q u e : a p p e l au c o n s t r u c t e u r de Thread
p u b l i c void run ( )
{
while ( true )
{
System . o u t . p r i n t l n ( " Pour ␣ l a ␣ "+ (++nbRuns ) +" e ␣ f o i s , ␣mon
␣nom␣ e s t ␣ :␣ " + getName ( ) ) ;
Thread . y i e l d ( ) ; // p e t i t e p a u s e
} } }
E. ADAM UPHF Java Avance UPHF/INSA HdF 5 / 42
Création de processus
Exemple de Thread (2/2)
Le programme principal est le processus principal
Partage des ressources machine entre les processus et le processus
principal
p u b l i c c l a s s MaTache
{
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] )
{
UneTache t a c h e 1 = new UneTache ( " t a c h e ␣ 1 " ) ;
UneTache t a c h e 2 = new UneTache ( " t a c h e ␣ 2 " ) ;
tache1 . s t a r t () ; tache2 . s t a r t () ;
int i = 0 ;
i n t f i n = 100 ;
w h i l e ( i <f i n )
{
System . o u t . p r i n t l n ( " I c i ␣ t a c h e ␣ p r i n c i p a l e , ␣ i=" + i ) ;
i ++ ;
Thread . y i e l d ( ) ;
}
System . e x i t ( 0 ) ;
}
}
E. ADAM UPHF Java Avance UPHF/INSA HdF 6 / 42
Création de processus
Exemple de Thread resultat
Résultat de l’exécution
Pour la 1e fois, mon nom est : tache 1
Pour la 2e fois, mon nom est : tache 1
Je suis la tache principale, i=0
Pour la 1e fois, mon nom est : tache 2
Pour la 3e fois, mon nom est : tache 1
Pour la 2e fois, mon nom est : tache 2
Je suis la tache principale, i=1
Pour la 4e fois, mon nom est : tache 1
Pour la 3e fois, mon nom est : tache 2
Je suis la tache principale, i=2
....
E. ADAM UPHF Java Avance UPHF/INSA HdF 7 / 42
Transformation en processus
Transformation en processus
interface Runnable
Si une classe étend une autre classe, elle ne peut étendre
Thread (pas d’héritage multiple)
La solution :
implémenter l’interface Runnable
définir la méthode run()
pour lancer un élément ‘runnable’, créer un Thread prenant en
paramètre cet élément
et démarrer ce processus
E. ADAM UPHF Java Avance UPHF/INSA HdF 8 / 42
Transformation en processus
Exemple d’utilisation de Runnable (1/2)
Le programme principal est le processus principal
Exemple de création d’une classe qui compte sans arrêt en
implémentant l’interface Runnable.
c l a s s Ob jetComptant i m p l e m e n t s R u n n a b l e
{
S t r i n g name ;
Ob jetComptant ( S t r i n g nom ) { name = nom ; }
p u b l i c void run ( )
{
i n t i =0 ;
while ( true )
{
System . o u t . p r i n t l n ( " moi ␣ " + name + " ␣ j ’ en ␣ s u i s ␣ a ␣ " + ( i
++)) ;
Thread . y i e l d ( ) ;
} } }
E. ADAM UPHF Java Avance UPHF/INSA HdF 9 / 42
Transformation en processus
Exemple d’utilisation de Runnable (2/2)
Le programme principal est le processus principal
Créer 2 processus à partir d’objets ‘Runable’
p u b l i c c l a s s MonRunnable
{
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] )
{
new Thread ( new ObjetComptant ( " c1 " ) ) . s t a r t ( ) ;
new Thread ( new ObjetComptant ( " c2 " ) ) . s t a r t ( ) ;
int i = 0 ;
w h i l e ( i <100)
{
System . o u t . p r i n t l n ( " J e ␣ s u i s ␣ l a ␣ t a c h e ␣ p r i n c i p a l e , ␣ i=" +
i);
i ++ ;
Thread . y i e l d ( ) ;
}
System . e x i t ( 0 ) ;
}
}
E. ADAM UPHF Java Avance UPHF/INSA HdF 10 / 42
Transformation en processus
Exemple d’utilisation de Runnable resultat
Résultat de l’exécution
moi c1 j’en suis à 0
moi c2 j’en suis à 0
Je suis la tache principale, i=0
moi c1 j’en suis à 1
moi c2 j’en suis à 1
Je suis la tache principale, i=1
moi c1 j’en suis à 2
moi c2 j’en suis à 2
Je suis la tache principale, i=2
moi c1 j’en suis à 3
moi c2 j’en suis à 3
Je suis la tache principale, i=3
....
E. ADAM UPHF Java Avance UPHF/INSA HdF 11 / 42
Processus et notation lambda
Création de processus en ligne par notation
lambda
Le programme principal est le processus principal
Création par notation lambda de deux processus, l’un comptant de
0 à 5, l’autre de 100 à 105
Attente tant qu’un des deux est encore en vie
p u b l i c c l a s s MonRunnable {
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
Thread p1 = new Thread ( ( )−>{ f o r ( i n t i =0 ; i ++<5 ; ) { System .
o u t . p r i n t l n ( " p1−>"+i ) ; Thread . y i e l d ( ) ; } } ) ;
Thread p2 = new Thread ( ( )−>{ f o r ( i n t i =100 ; i ++<105 ; ) {
System . o u t . p r i n t l n ( " p2−>"+i ) ; Thread . y i e l d ( ) ; } } ) ;
p1 . s t a r t ( ) ; p2 . s t a r t ( ) ;
w h i l e ( p1 . i s A l i v e ( ) | | p2 . i s A l i v e ( ) ) Thread . y i e l d ( ) ;
System . e x i t ( 0 ) ;
}
}
E. ADAM UPHF Java Avance UPHF/INSA HdF 12 / 42
Processus et notation lambda
Création de processus en ligne par notation
lambda resultat
Résultat de l’exécution
p1->0
p2->100
p1->1
p2->101
p2->102
p2->103
p2->104
p1->2
p1->3
p1->4
Ils ont fini !!!
E. ADAM UPHF Java Avance UPHF/INSA HdF 13 / 42
Groupe de processus
Groupement de processus 1/2
Grouper les processus pour mieux les gérer
Possibilité d’associer des processus à des groupes (ThreadGroup) ;
possibilité d’associer des groupes à des groupes
quelques méthodes :
activeCount() : nombre de processus actifs dans le groupe
enumerate(Thread[] tab) :place dans tab la liste des processus actifs
interrupt() : interrompt tous les processus du groupe
join() : appel bloquant, attend que le processus meure
join(long delai) : attend au plus delai ms que le processus meure
ThreadGroup g r o u p e = new ThreadGroup ( "mon␣ g r o u p e " ) ;
Thread p1 = new Thread ( g r o u p e , ( )−>{ f o r ( i n t i =0 ; i <5 ; i ++){
System . o u t . p r i n t l n ( " p1−>" + i ) ; Thread . y i e l d ( ) ; } } ) ;
Thread p2 = new Thread ( g r o u p e , ( )−>{ f o r ( i n t i =100 ; i <105 ; i
++){ System . o u t . p r i n t l n ( " p2−>" + i ) ; Thread . y i e l d ( ) ; } } ) ;
p1 . s t a r t ( ) ; p2 . s t a r t ( ) ;
w h i l e ( g r o u p e . a c t i v e C o u n t ( ) !=0 ) Thread . y i e l d ( ) ;
System . e r r . p r i n t l n ( " I l s ␣ o n t ␣ f i n i ␣ ! ! ! " ) ;
E. ADAM UPHF Java Avance UPHF/INSA HdF 14 / 42
Groupe de processus
Groupement de processus 2/2
Relation processus-groupe
Création de processus
Thread(Runnable cible) : crée un processus sur l’objet cible
Thread(Runnable cible, String nom) : crée un processus sur l’objet
cible et donne un nom
Thread(ThreadGroup groupe, Runnable cible, String nom) : crée un
processus sur l’objet cible, lui donne un nom et l’affecte à un groupe
Thread(ThreadGroup groupe, Runnable cible) : crée un processus
sur l’objet cible et l’affecte à un groupe, le nom est donné
automatiquement
retrouver le groupe, le processus
getThreadGroup() : dans la classe Thread retourne le groupe auquel
appartient le processus
[Link]() : retourne le processus exécutant la
methode
E. ADAM UPHF Java Avance UPHF/INSA HdF 15 / 42
Planification de processus
Planifier l’exécution de processus 1/3
Tâche planifiée
Une tâche planifiée est de type TimerTask, elle possède les
méthodes
cancel() : annule la tâche
run() : action exécutée par la tâche
scheduledExecutionTime() : retourne la prochaine date en ms à
laquelle run() va être exécutée
//EXEMPLE DE TACHE QUI AFFICHE L ’HEURE
import j a v a . time . LocalTime ;
i m p o r t j a v a . u t i l . TimerTask ;
import j a v a . time . format . DateTimeFormatter ;
c l a s s M a T a c h e P l a n i f i e e e x t e n d s TimerTask
{
p u b l i c void run ( ) {
System . o u t . p r i n t l n ( L o c a l T i m e . now ( ) . f o r m a t (
D a t e T i m e F o r m a t t e r . o f P a t t e r n ( " hh :mm : s s " ) ) + " ␣−>␣
E x e c u t i o n ␣ de ␣ma␣ t a c h e " ) ;
}
} E. ADAM UPHF Java Avance UPHF/INSA HdF 16 / 42
Planification de processus
Planifier l’exécution de processus 2/3
Planification par Timer
Un Timer ([Link]) est un objet qui peut temporiser
l’exécution de tâche de time [Link]. La classe Timer
propose les méthodes
schedule(TimerTask task, long delay) : planifie l’exécution de la
tâche après un delai
schedule(TimerTask task, long delay, long period) : planifie
l’exécution de la tâche après un delai, et cylciquement selon une
période
schedule(TimerTask task, Date moment) : planifie l’exécution de la
tâche à une date donnée
...
E. ADAM UPHF Java Avance UPHF/INSA HdF 17 / 42
Planification de processus
Planifier l’exécution de processus 3/3
Timer t i m e r = new Timer ( ) ;
// l a n c e m e n t de l a t a c h e d a n s 1 s e c , e t l a r e p e t e r t o u t e s l e s
5 sec .
t i m e r . s c h e d u l e ( new M a T a c h e P l a n i f i e e ( ) , 1 0 0 0 , 5 0 0 0 ) ;
// a t t e n d r e 12 s e c .
t r y { Thread . s l e e p ( 1 2 0 0 0 ) ; } c a t c h ( I n t e r r u p t e d E x c e p t i o n e )
{}
// a n n u l e r l a p l a n i f i c a t i o n
timer . cancel () ;
System . o u t . p r i n t l n ( L o c a l T i m e . now ( ) . f o r m a t ( D a t e T i m e F o r m a t t e r .
o f P a t t e r n ( " hh :mm : s s " ) ) + " ␣−>␣ FIN ␣ ! ! " ) ;
Résultat de l’exécution
10:50:21 -> Execution de ma tache
10:50:26 -> Execution de ma tache
10:50:31 -> Execution de ma tache
10:50:32 -> FIN !!
E. ADAM UPHF Java Avance UPHF/INSA HdF 18 / 42
Synchronisation Principes de la synchronisation
Principes de la synchronisation
Problème d’accès mutuel à une même ressource
Supposons deux transporteurs voulant stocker une palette
dans un entrepôt
Un transporteur vérifie la capacité à distance par une appli sur
smartphone et perçoit qu’il reste une place
Un autre transporteur fait de même
E. ADAM UPHF Java Avance UPHF/INSA HdF 19 / 42
Synchronisation Principes de la synchronisation
Principes de la synchronisation
Problème d’accès mutuel à une même ressource
Les deux transporteurs arrivent pour stocker leur palette
Un conflit survient !
E. ADAM UPHF Java Avance UPHF/INSA HdF 20 / 42
Synchronisation Principes de la synchronisation
Principes de la synchronisation
Solution à l’accès mutuel à une même ressource
L’entrepôt doit gérer les conflits
Dès qu’un transporteur fait une demande, les autres sont mis
en attente tant que la demande n’est pas traitée
E. ADAM UPHF Java Avance UPHF/INSA HdF 21 / 42
Synchronisation Principes de la synchronisation
Principes de la synchronisation
Solution à l’accès mutuel à une même ressource
Une réponse est ensuite envoyée :
Soit une autorisation d’accès, soit mise en attente
E. ADAM UPHF Java Avance UPHF/INSA HdF 22 / 42
Synchronisation Synchronisation de méthode
Synchronisation de méthode
Eviter l’accès mutuel à une méthode
Pour bloquer l’accès mutuel à une fonction,
celle-ci doit être précédée du mot clé synchronized
Si un processus appelle une fonction synchronisée dans lequel
se trouve déjà un processus, il est bloqué au portes de la
fonction.
Il entrera dans la fonction si :
le processus l’utilisant en sort
et qu’aucun autre processus n’était mis en attente avant lui
le processus l’utilisant est mis en attente (wait())
et qu’aucun autre processus n’était mis en attente avant lui
E. ADAM UPHF Java Avance UPHF/INSA HdF 23 / 42
Synchronisation Synchronisation de méthode
Synchronisation de méthode : Exemple (1/3)
/∗ ∗ c l a s s e s i m p l e p o s s e d a n t une f o n c t i o n s y n c h o n i s e e ∗/
public class ClasseSynchro {
C l a s s e S y n c h r o ( ) {}
/∗ ∗ f o n c t i o n s y n c h o n i s e e :
bloque l e s processus appelants s i l e parametre est impair
l e s r e v e i l l e s i un p r o c e s s u s a r r i v e a v e c un p a r a m e t r e p a i r ∗/
public synchronized void testPair ( int i ) {
System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " , ␣ j e
␣ suis ␣ entre ") ;
t r y { Thread . s l e e p ( 2 0 0 0 ) ; } c a t c h ( E x c e p t i o n e1 ) { }
i f ( ( i % 2 ) != 0 )
{
System . o u t . p r i n t l n ( " l e ␣ nb ␣n ’ e s t ␣ p a s ␣ p a i r , ␣ j e ␣ mets ␣ en ␣
attente ") ;
t r y { wait () ; } catch ( I n t e r r u p t e d E x c e p t i o n e ) { }
}
e l s e System . o u t . p r i n t l n ( " l e ␣ nb ␣ e s t ␣ p a i r " ) ;
System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣
s o r t ␣ de ␣ l a ␣ f o n c t i o n " ) ;
}
}
E. ADAM UPHF Java Avance UPHF/INSA HdF 24 / 42
Synchronisation Synchronisation de méthode
Synchronisation de méthode : Exemple (2/3)
C l a s s e S y n c h r o c l a s s e S y n c h r o = new C l a s s e S y n c h r o ( ) ;
Thread p1 = new Thread ( ( )−>c l a s s e S y n c h r o . t e s t P a i r ( 3 ) , " p1 " ) ;
Thread p2 = new Thread ( ( )−>c l a s s e S y n c h r o . t e s t P a i r ( 5 ) , " p2 " ) ;
Thread p3 = new Thread ( ( )−>c l a s s e S y n c h r o . t e s t P a i r ( 4 ) , " p3 " ) ;
p1 . s t a r t ( ) ;
p2 . s t a r t ( ) ;
t r y { Thread . s l e e p ( 5 0 0 0 ) ; } c a t c h ( I n t e r r u p t e d E x c e p t i o n e ) {
e . p r i n t S t a c k T r a c e ( ) ;}
p3 . s t a r t ( ) ;
Résultat de l’exécution
p1, je suis entré
le nb n’est pas pair, je mets en attente
p2, je suis entré
le nb n’est pas pair, je mets en attente
p3, je suis entré
le nb est pair
p3 sort de la fonction
E. ADAM UPHF Java Avance UPHF/INSA HdF 25 / 42
Synchronisation Synchronisation de méthode
Synchronisation de méthode : Exemple (3/3)
Résultat de l’exécution
p1 et p2 ne sortent jamais de la méthode run() !
ils restent endormis
→ modification pour qu’un processus ayant donné un nombre
pair réveille tous les processus mis en attente
ajout de la fonction notify() (réveille un processus)
ou de notifyAll() (réveille tous les processus)
E. ADAM UPHF Java Avance UPHF/INSA HdF 26 / 42
Synchronisation Synchronisation de méthode
Réveil de processus : Exemple (1/2)
/∗ ∗ c l a s s e s i m p l e p o s s e d a n t une f o n c t i o n s y n c h o n i s e e ∗/
public class ClasseSynchro {
C l a s s e S y n c h r o ( ) {}
/∗ ∗ f o n c t i o n s y n c h o n i s e e :
bloque l e s processus appelants s i l e parametre est impair
l e s r e v e i l l e s i un p r o c e s s u s a r r i v e a v e c un p a r a m e t r e p a i r ∗/
public synchronized void testPair ( int i ) {
System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " , ␣ j e
␣ suis ␣ entre ") ;
t r y { Thread . s l e e p ( 2 0 0 0 ) ; } c a t c h ( E x c e p t i o n e1 ) { }
i f ( ( i % 2 ) != 0 )
{
System . o u t . p r i n t l n ( " l e ␣ nb ␣n ’ e s t ␣ p a s ␣ p a i r , ␣ j e ␣ mets ␣ en ␣
attente ") ;
t r y { wait () ; } catch ( I n t e r r u p t e d E x c e p t i o n e ) { }
}
else {
System . o u t . p r i n t l n ( " l e ␣ nb ␣ e s t ␣ p a i r " ) ;
n o t i f y A l l () ;
System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣
s o r t ␣ de ␣ l a ␣ f o n c t i o n " ) ;
}
} E. ADAM UPHF Java Avance UPHF/INSA HdF 27 / 42
Synchronisation Synchronisation de méthode
Réveil de processus : Exemple (2/2)
Résultat de l’exécution
Cette fois à l’exécution, on obtient :
p1, je suis entré
le nb n’est pas pair, je mets en attente
p2, je suis entré
le nb n’est pas pair, je mets en attente
p3, je suis entré
le nb est pair
p3 sort de la fonction
p1 sort de la fonction
p2 sort de la fonction
p1 et p3 sortent de la méthode run() !
E. ADAM UPHF Java Avance UPHF/INSA HdF 28 / 42
Synchronisation Mise en veille et Réveil de processus
Mise en veille et Réveil de processus
wait() and notify()
Placée dans une fonction d’un objet, l’appel à la fonction
wait() met en veille le processus appelant
Placée dans une fonction d’un objet, notify() réveille un
processus mis en veille dans une des procédures de l’objet
Placée dans une fonction d’un objet, notifyAll() réveille tous
les processus mis en veille dans une des procédures de l’objet
E. ADAM UPHF Java Avance UPHF/INSA HdF 29 / 42
Exemple type : les producteur et les consommateurs Présentation
Exemple type : les producteur et les
consommateurs
Producteurs et Consommateurs : Enoncé
Il existe un Entrepôt de taille limitée (n)
np producteurs produisent régulièrement des produits qu’ils
cherchent à stocker dans l’entrepôt
nc consommateurs tentent régulièrement de retirer des
produits de l’entrepôt
Les producteurs et consommateurs sont des processus
partageant le même entreprôt
le dépôt d’objets et le retrait d’objet doit donc être
synchronisé
E. ADAM UPHF Java Avance UPHF/INSA HdF 30 / 42
Exemple type : les producteur et les consommateurs Codes
Producteurs et consommateurs : définition de
l’entrepôt I
c l a s s Entrepot {
private int [ ] stockage ;
p r i v a t e i n t t a i l l e , nbDeposes , n b P r i s , n b O b j e t s C o u r a n t s ;
public Entrepot ( int _ t a i l l e ) {
s t o c k a g e = new i n t [ _ t a i l l e ] ; taille = _taille ;
}
p u b l i c synchronized void depose ( i n t obj ) {
// t q que l e t a b l e a u e s t p l e i n , m e t t r e en p a u s e
w h i l e ( n b O b j e t s C o u r a n t s == ( t a i l l e − 1 ) ) {
// a f f i c h e l e nom du p r o c e s s u s a p p e l a n t e t m i s en p a u s e
System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + "−−
␣ p a u s e ␣ d a n s ␣ l e ␣ d e p o t ␣d ’ o b j e t " ) ;
t r y { wait () ; } catch ( I n t e r r u p t e d E x c e p t i o n e ) { }
}
stockage [ nbObjetsCourants ] = obj ;
n b O b j e t s C o u r a n t s++ ; n b D e p o s e s++ ;
// r e v e i l l e r d e s a u t r e s p r o c e s s u s au c a s ou
E. ADAM UPHF Java Avance UPHF/INSA HdF 31 / 42
Exemple type : les producteur et les consommateurs Codes
Producteurs et consommateurs : définition de
l’entrepôt II
n o t i f y A l l () ;
}
public synchronized int preleve () {
// t q que l e t a b l e a u e s t v i d e , m e t t r e en p a u s e
w h i l e ( n b O b j e t s C o u r a n t s == 0 ) {
// a f f i c h e l e nom du p r o c e s s u s a p p e l a n t e t m i s en p a u s e
System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + "−−
p a u s e ␣ d a n s ␣ l e ␣ r e t r a i t ␣d ’ o b j e t " ) ;
t r y { wait () ; } catch ( I n t e r r u p t e d E x c e p t i o n e ) { }
}
i n t obj = stockage [ nbObjetsCourants − 1] ;
n b O b j e t s C o u r a n t s −− ; n b P r i s++ ;
// r e v e i l l e r d e s a u t r e s p r o c e s s u s au c a s ou
n o t i f y A l l () ;
return obj ;
}
}
E. ADAM UPHF Java Avance UPHF/INSA HdF 32 / 42
Exemple type : les producteur et les consommateurs Codes
Producteurs et consommateurs : définition du
Producteur I
c l a s s P r o d u c t e u r e x t e n d s Thread {
/∗ ∗ l i e n v e r s l ’ e n t r e p o t ∗/
Entrepot entrepot ;
/∗ ∗ i n d i q u e s i l e p r o c e s s u s d o i t s ’ a r r e t e r ∗/
p r i v a t e boolean a r r e t = f a l s e ;
/∗ ∗ t o t a l d e s o b j e t s p r o d u i t s ∗/
p r i v a t e s t a t i c i n t nbObjets = 0 ;
/∗ ∗ no du p r o d u i t a d e p o s e r ∗/
p r i v a t e i n t noObjet = 0 ;
p u b l i c P r o d u c t e u r ( S t r i n g _nom , E n t r e p o t _ e n t r e p o t )
{ s u p e r (_nom) ; e n t r e p o t = _ e n t r e p o t ;
n o O b j e t = n b O b j e t s ++ ;}
E. ADAM UPHF Java Avance UPHF/INSA HdF 33 / 42
Exemple type : les producteur et les consommateurs Codes
Producteurs et consommateurs : définition du
Producteur II
p u b l i c void run ( )
{
// t a n t que l ’ a r r e t n ’ e s t p a s demande
while ( ! arret ) {
n o O b j e t = n b O b j e t s++ ;
// t e n t e de d e p o s e r
e n t r e p o t . depose ( noObjet ) ;
System . o u t . p r i n t l n ( getName ( ) + " ␣ :␣ j ’ a i ␣ d e p o s e ␣ l ’ o b j e t ␣ "+
noObjet ) ;
// p e t i t e p a u s e de 100ms maxi
t r y { Thread . s l e e p ( ( i n t ) ( Math . random ( ) ∗ 1 0 0 ) ) ;}
c a t c h ( I n t e r r u p t e d E x c e p t i o n e ) {}
}
}
/∗ ∗ p e r m e t de demander l ’ a r r e t du p r o c e s s u s ∗/
public void halte () { a r r e t = true ; }
}
E. ADAM UPHF Java Avance UPHF/INSA HdF 34 / 42
Exemple type : les producteur et les consommateurs Codes
Producteurs et consommateurs : définition du
Consommateur
c l a s s Consommateur e x t e n d s Thread {
/∗ ∗ l i e n v e r s l ’ e n t r e p o t ∗/
Entrepot entrepot ;
boolean a r r e t = f a l s e ;
p u b l i c Consommateur ( S t r i n g _nom , E n t r e p o t _ent )
{ s u p e r (_nom) ; e n t r e p o t = _ent ; }
p u b l i c void run ( ) {
// t a n t que l ’ a r r e t n ’ e s t p a s demande
while ( ! arret ) {
int obj = entrepot . preleve () ;
System . o u t . p r i n t l n ( getName ( ) + " :␣ j ’ a i ␣ ␣ l ’ o b j e t ␣ " + o b j ) ;
// p e t i t e p a u s e de 200ms maxi
t r y { Thread . s l e e p ( ( i n t ) ( Math . random ( ) ∗ 2 0 0 ) ) ; }
c a t c h ( I n t e r r u p t e d E x c e p t i o n e ) {}
} }
public void halte () { a r r e t = true ; } }
E. ADAM UPHF Java Avance UPHF/INSA HdF 35 / 42
Exemple type : les producteur et les consommateurs Codes
Producteurs et consommateurs : Lancer la
Simu
c l a s s ProductConsom {
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
// c r e e r un e n t r e p o t l i m i t e a 10 p l a c e s
E n t r e p o t t a b = new E n t r e p o t ( 1 0 ) ;
P r o d u c t e u r p r o d 1 = new P r o d u c t e u r ( " p r o d u c t 1 " , t a b ) ;
P r o d u c t e u r p r o d 2 = new P r o d u c t e u r ( " p r o d u c t 2 " , t a b ) ;
Consommateur c o n s 1 = new Consommateur ( " consom ␣ 1 " , t a b ) ;
Consommateur c o n s 2 = new Consommateur ( " consom ␣ 2 " , t a b ) ;
Consommateur c o n s 3 = new Consommateur ( " consom ␣ 3 " , t a b ) ;
P r o d u c t e u r [ ] t a b P r o d = { prod1 , p r o d 2 } ;
Consommateur [ ] t a b C o n s = { c on s1 , c on s2 , c o n s 3 } ;
f o r ( i n t i = 0 ; i <t a b P r o d . l e n g t h ; i ++) t a b P r o d [ i ] . s t a r t ( ) ;
f o r ( i n t i = 0 ; i <t a b C o n s . l e n g t h ; i ++) t a b C o n s [ i ] . s t a r t ( ) ;
// f a i r e t o u r n e r l e s p r o c e s s u s 4 s e c o n d e s
t r y { Thread . s l e e p ( 4 0 0 0 ) ;} c a t c h ( I n t e r r u p t e d E x c e p t i o n e ) {}
for ( int i = 0 ; i <t a b P r o d . l e n g t h ; i ++) t a b P r o d [ i ] . h a l t e ( ) ;
for ( int i = 0 ; i <t a b C o n s . l e n g t h ; i ++) t a b C o n s [ i ] . h a l t e ( ) ;
System . o u t . p r i n t l n ( t a b ) ; }}
E. ADAM UPHF Java Avance UPHF/INSA HdF 36 / 42
Volatilité
Volatilité : pour forcer l’écriture en mémoire
Mémoire centrale et mémoire cache
La JVM de Java est composée d’une mémoire centrale et
d’une mémoire cache
Un changement de valeur d’une variable s’effectue en mémoire
cache
Si un processus souhaite accéder à la variable, il reçoit la
valeur de la mémoire centrale
Certains attributs doivent donc être rafraîchis en permanence
→ Utilisation du mot clé volatile
E. ADAM UPHF Java Avance UPHF/INSA HdF 37 / 42
Volatilité
Volatilité : pour forcer l’écriture en mémoire
Mot clé volatile
int volatile valeur = 0 ;
Les attributs volatiles :
sont chargés de la mémoire centrale avant chaque utilisation.
sont stockés en mémoire centrale après chaque accès/écriture.
A utiliser si une variable est partagée, hors d’un bloc
synchronisé
E. ADAM UPHF Java Avance UPHF/INSA HdF 38 / 42
Bloc synchronisé
Créer un bloc synchronisé
Possibilité de synchroniser un bloc d’un code
...
s y n c h r o n i z e d ( c o m p t e u r ) { c o m p t e u r . add ( ) ; c o m p t e u r . m u l t ( ) ; }
...
→ synchronise l’accès à l’objet compteur.
Lorsqu’une méthode synchronisée d’un objet est appelée, le
verrou est mis, aucune autre méthode synchronisée de cet
objet peut être exécutée.
tant que le processus n’est pas sorti.
sauf s’il a été mis en attente (wait)
Acquérir le verrou d’un objet est forcément coûteux.
Il faut donc savoir gérer et diminuer au maximum les sections
critiques.
E. ADAM UPHF Java Avance UPHF/INSA HdF 39 / 42
Communication entre processus
Communication entre processus
Tube de communication
Si un processus veut envoyer une donnée à un autre processus,
il peut appeler une fonction, ou communiquer par envoi de
message
Pour cela, il faut créer un tube de communication
L’émetteur reçoit l’entrée du tube,
Le destinataire reçoit la sortie du tube.
P i p e d W r i t e r o u t = new P i p e d W r i t e r ( ) ;
P i p e d R e a d e r i n=n u l l ;
t r y { i n = new P i p e d R e a d e r ( o u t ) ; }
catch ( IOException e ) {e . printStackTrace () ; }
E. ADAM UPHF Java Avance UPHF/INSA HdF 40 / 42
Communication entre processus
Exemple de communication de chaînes de
caractères I
P i p e d W r i t e r o u t = new P i p e d W r i t e r ( ) ;
P i p e d R e a d e r i n=n u l l ;
t r y { i n = new P i p e d R e a d e r ( o u t ) ; }
catch ( IOException e ) {e . printStackTrace () ; }
f i n a l P r i n t W r i t e r s t r O u t = new P r i n t W r i t e r ( o u t ) ;
f i n a l B u f f e r e d R e a d e r s t r I n = new B u f f e r e d R e a d e r ( i n ) ;
Thread s e n d e r=new Thread ( ( )−> {
S c a n n e r s c = new S c a n n e r ( System . i n ) ;
String ligne = "" ;
w h i l e ( ! l i g n e . e q u a l s ( " end " ) ) {
System . o u t . p r i n t l n ( " s e n d e r −>e n t r e z ␣ une ␣ c h a i n e ␣ :␣ " ) ;
l i g n e = sc . nextLine () ;
t r y { s t r O u t . p r i n t l n ( l i g n e ) ; } c a t c h ( E x c e p t i o n e ) {}
}} ) ;
E. ADAM UPHF Java Avance UPHF/INSA HdF 41 / 42
Communication entre processus
Exemple de communication de chaînes de
caractères II
Thread r e c e i v e r=new Thread ( ( )−> {
String ligne = "" ;
w h i l e ( ! l i g n e . e q u a l s ( " end " ) ) {
t r y { l i g n e= s t r I n . r e a d L i n e ( ) ;} c a t c h ( I O E x c e p t i o n e ) {}
System . o u t . p r i n t l n ( " r e c e i v e r ␣−>␣ r e c u ␣ " + l i g n e ) ;
}} ) ;
sender . s t a r t () ;
re ce iv e r . start () ;
E. ADAM UPHF Java Avance UPHF/INSA HdF 42 / 42