0% ont trouvé ce document utile (0 vote)
38 vues42 pages

Gestion Avancée des Processus Java

Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
38 vues42 pages

Gestion Avancée des Processus Java

Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

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
[Link] -> Execution de ma tache
[Link] -> Execution de ma tache
[Link] -> Execution de ma tache
[Link] -> 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

Vous aimerez peut-être aussi