Les threads en Javapageperso.lif.univ-mrs.fr/~arnaud.labourel/PPD/cours2.pdfLes threads en Java...

Preview:

Citation preview

Les threads en Java

Arnaud LabourelCourriel : arnaud.labourel@lif.univ-mrs.fr

Universite de Provence

26 janvier 2012

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Au Temps des Dinosaures...

et des cartes perforees, les ordinateurs etaient de grossesinstallations sur lesquelles on pouvait soumettre untravail puis venir recuperer le resultat quelques heuresplus tard.

Si un probleme se produisait en cours d’execution, on nele savait que plus tard et le temps affecte etait perdu...

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Multi-Taches

Le multi-taches permet de

optimiser l’utilisation des ressources (CPU, ...)

faciliter la programmation (modularisation)faciliter l’equite

Serveur multi-utilisateursStation mono-utilisateur : systeme plus “reactif”

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Processus et Threads

Une activite est une suite d’instructions (executionsequentielle.)

Un systeme est multi-tache s’il peut faire coexisterplusieurs activites au sein d’un meme environnement.

Un processus est une activite seule au sein d’unenvironnement restreint (memoire ...).

Au contraire un thread (ou processus leger) partage toutun environnement memoire avec d’autres threads.

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Exemples

Activites :

processus UNIX

threads POSIX

threads Java

Systemes d’exploitation :

Windows (NT, 2000, XP, Vista, seven)

SolarisUnix :

Les Unix proprietaires (AIX, HP UX, ...)BSDLinux (vrais threads depuis 2.6)Mac OS X

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Creation de Threads en Java

Deux manieres de faire :Classe Thread

methode run : code de l’activitemethode start : lancement de l’activitemethodes de controle ...=⇒par heritage de Thread.

interface Runnableune unique methode (abstraite) public void run() :code de l’activitepar implementation de Runnable+ constructeurs de la classe Thread

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Creation de Threads en Java

Deux manieres de faire :Classe Thread

methode run : code de l’activitemethode start : lancement de l’activitemethodes de controle ...=⇒par heritage de Thread.

interface Runnableune unique methode (abstraite) public void run() :code de l’activitepar implementation de Runnable+ constructeurs de la classe Thread

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Rappels : “Heritages Multiples”

Pourquoi deux manieres de faire ?

Rappel : Java n’autorise pas l’heritage multiple.

Une classe ne peut etre l’extension (ne peux heriter) qued’une seule classe.Par contre elle peut implementer plusieurs interfaces.Rappel : une interface n’a pas de variable d’instance etn’a que des methodes abstraites...

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Comment choisir entre les deux solutions ?

Heriter de Thread : quand on n’a pas besoind’heriter d’une autre classe.

Implementer Runnable : quand on souhaiteheriter d’une autre classe.

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Exemple : ExThread.javac l a s s ExThread extends Thread {

i n t i d ;

ExThread ( i n t v a l ) {/∗ c o n s t r u c t e u r ∗/i d = v a l ;}

/∗ Methode e x e c u t e e par l e t h r e a d ∗/publ ic void run ( ) {. . .}. . .

fo r ( i n t i =1; i<=n ; i ++)new ExThread ( i ) . s t a r t ( ) ;

. . .}

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Exemple : ExRunnable.javac l a s s ExRunnable implements Runnable {

i n t i d ;

ExThread ( i n t v a l ) {/∗ c o n s t r u c t e u r ∗/i d = v a l ;}

/∗ Methode e x e c u t e e par l e t h r e a d ∗/publ ic void run ( ) {. . .}. . .

fo r ( i n t i =1; i<=n ; i ++)new Thread (new ExRunnable ( i ) ) . s t a r t ( ) ;

. . .}

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Remarque Importante

Ne pas confondre l’activite (le thread : processus leger)avec la structure de donnees (le Thread : l’objet).

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Information sur les Threads

static int activeCount() : renvoie le nombre dethreads actuellement executes

static int enumerate(Thread[] tarray) :stocke l’ensemble des Threads du meme groupedans le tableau et renvoie le nombre de threads.

static Thread currentThread() : renvoie leThread correspondant au thread en train d’etreexecute. (utile notamment avec Runnable)

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Autres methodes sur les Threads

void setName(String name) : change le nom duThread

String getName() : retourne le nom du Thread

new Thread(ThreadGroup group,Runnable target , String name) : cree un

Thread dans un groupe.

new ThreadGroup(”Mon groupe”) : cree ungroupe de Thread

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Ordonnancement

L’ordonnanceur de la JVM n’est pas tenu d’etreequitable. Les threads de basses priorites ne sontexecutes que si les threads de hautes priorites sontbloques...

void setPriority ( int ) : fixer la priorite du thread

int getPriority () : renvoie la priorite du thread

static void yield () : provoque une “pause” duthread en cours et un reordonnancement (indicatifseulement...)

L’ordonnanceur n’est pas tenu de tenir compte despriorites...=⇒inutilisable de maniere portable.

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Manipulation des Threads

mise en attente :void sleep (long millis )void sleep (long millis , int nanos)

NB : pas de garantie temps-reelattente de l’arret d’un thread donne :

void join ()void join (long millis ) avec delaivoid join (long millis , int nanos) avec delai

interruption d’un thread :

void interrupt () : un thread “interrompt” (envoie uneInterruptedException ) un autre.

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Rappels : Exceptions

Certaines des methodes precedentes (bloquantes)demandent une gestion explicite des interruptions partry{ ... } catch(InterruptedException e){ ... }Une exception correspond en general a un deroulementanormal du programme. De plus, dans le casmulti-threade, cela peut correspondre a certainesinteractions entre threads.

Erreur inhabituelle =⇒gestion d’erreur classique

Declenchement d’une exception

Gestion des interruptions/exceptions.

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Throwable

unchecked exception : erreur engendree par la JVM(interaction systeme) =⇒ne doit pasnecessairement etre geree.

checked exception : erreur definie par l’utilisateur,doit necessairement etre geree (=⇒throws)

Ici, plus particulierement, InterruptedException .

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

try, catch, finally

. . .t ry {/∗ a p p e l a une methode l a n c a n t des e x c e p t i o n s ∗/

. . .} catch ( TypeExcept ion e ){

. . .} catch ( A u t r e T y p e E x c e p t i o n e ){

. . .} f i n a l l y { // t o u j o u r s e x e c u t e

. . .}

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Variables Partagees

Les variables de la classe declarees en static sontpartagees entre tous les threads associes a cette classe.

Il est conseille de rajouter le mot clef volatile pourproteger la variable de certaines “optimisations” de laJVM.

Voir, plus tard, le package atomic, puis les questions devisibilite et du modele memoire Java.

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Synchronisation et Exclusion Mutuelle

Le mot-clef synchronized permet de gerer lasynchronisation des acces a la memoire partagee.

Un appel a une methode declaree synchronized d’uneinstance donnee est en exclusion mutuelle vis-a-vis detous les appels de methodes declarees synchronized surcette meme instance.

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Tres Important : Methodologie

Il faudra toujours bien separer donnees partagees etactivites=⇒au moins Deux classes.

Voir VariablePartagee.java,VariableSynchronized.java,VariableBienSynchronized.java.

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

VariablePartagee.java

c l a s s E n t i e r P a r t a g e{

i n t v a l e u r ;

E n t i e r P a r t a g e ( i n t v a l e u r ){t h i s . v a l e u r = v a l e u r ;

}

v o i d decremente ( i n t dec ){v a l e u r −= dec ;

}

p u b l i c S t r i n g t o S t r i n g (){r e t u r n S t r i n g . v a l u e O f ( v a l e u r ) ;

}}

c l a s s V a r i a b l e P a r t a g e e extends Thread {s t a t i c v o l a t i l e E n t i e r P a r t a g e v a r p a r t ;i n t i d ;

V a r i a b l e P a r t a g e e ( i n t i d ) {t h i s . i d = i d ;

}

p u b l i c v o i d run ( ) {w h i l e ( v a r p a r t . v a l e u r >= i d ){

a f f i c h e ( ” Avant ”+v a r p a r t ) ;v a r p a r t . decremente ( i d ) ;a f f i c h e ( ” Apr e s ”+v a r p a r t ) ;t r y { s l e e p ( 0 , 0 ) ;}catch ( I n t e r r u p t e d E x c e p t i o n e ){ a f f i c h e ( ” I n t e r r o m p u ” ) ;}

}a f f i c h e ( ” Termine ( ”+v a r p a r t+” ) ” ) ;

}

v o i d a f f i c h e ( S t r i n g s ){System . out . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ()+” : ”+s ) ;

}

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 ) {i n t n = 3 , v a l =9;

v a r p a r t = new E n t i e r P a r t a g e ( v a l ) ;f o r ( i n t i =1; i<=n ; i ++)

new V a r i a b l e P a r t a g e e ( i ) . s t a r t ( ) ;System . out . p r i n t l n ( ”Main : v a l e u r = ”+v a l ) ;System . out . p r i n t l n ( ”Main : I l y a ”+n+” t h r e a d s , l a r e g l e du j e u e s t chaque t h r e a d ne ” ) ;System . out . p r i n t l n ( ”Main : peut r e t i r e r qu ’ un nombre de p o i n t s e g a l e a son i d e n t i t e .\n” ) ;

}}

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

VariablePartageeSynchronized.java

c l a s s E n t i e r P a r t a g e{

i n t v a l e u r ;

E n t i e r P a r t a g e ( i n t v a l e u r ){t h i s . v a l e u r = v a l e u r ;

}

s y n c h r o n i z e d v o i d decremente ( i n t dec ){v a l e u r −= dec ;

}

p u b l i c S t r i n g t o S t r i n g (){r e t u r n S t r i n g . v a l u e O f ( v a l e u r ) ;

}}

c l a s s V a r i a b l e P a r t a g e e Sextends Thread {

s t a t i c E n t i e r P a r t a g e v a r p a r t ;i n t i d ;

V a r i a b l e P a r t a g e e B S ( i n t i d ) {t h i s . i d = i d ;

}

p u b l i c v o i d run ( ) {w h i l e ( v a r p a r t . v a l e u r>=i d ){

a f f i c h e ( ” Avant ”+v a r p a r t ) ;v a r p a r t . decremente ( i d ) ;a f f i c h e ( ” Apr e s ”+v a r p a r t ) ;t r y { s l e e p ( 0 , 0 ) ;}catch ( I n t e r r u p t e d E x c e p t i o n e ){a f f i c h e ( ” I n t e r r o m p u ” ) ;

}}a f f i c h e ( ” Termine ( ”+v a r p a r t+” ) ” ) ;}

v o i d a f f i c h e ( S t r i n g s ){System . out . p r i n t l n (

Thread . c u r r e n t T h r e a d ( ) . getName ()+” : ”+s ) ;}

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 ) {i n t n = 3 , v a l =9;

v a r p a r t = new E n t i e r P a r t a g e ( v a l ) ;f o r ( i n t i =1; i<=n ; i ++)

new V a r i a b l e P a r t a g e e S ( i ) . s t a r t ( ) ;System . out . p r i n t l n ( ”Main : v a l e u r = ”+v a l ) ;System . out . p r i n t l n ( ”Main : I l y a”+n+” t h r e a d s , ”

+” l a r e g l e du j e u e s t chaque t h r e a d ne ” ) ;System . out . p r i n t l n ( ”Main : peut r e t i r e r qu ’ un”

+” nombre de p o i n t s e g a l e a son i d e n t i t e .\n” ) ;}

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

VariablePartageeBienSynchronized.javac l a s s E n t i e r P a r t a g e{

i n t v a l e u r ;

E n t i e r P a r t a g e ( i n t v a l e u r ){t h i s . v a l e u r = v a l e u r ;

}

s y n c h r o n i z e d v o i d decremente ( i n t dec ){v a l e u r −= dec ;

}

s y n c h r o n i z e d boolean t e s t e ( i n t v ){r e t u r n ( v a l e u r>=v ) ;

}

p u b l i c S t r i n g t o S t r i n g (){r e t u r n S t r i n g . v a l u e O f ( v a l e u r ) ;

}}

c l a s s V a r i a b l e P a r t a g e e B Sextends Thread {

s t a t i c E n t i e r P a r t a g e v a r p a r t ;i n t i d ;

V a r i a b l e P a r t a g e e B S ( i n t i d ) {t h i s . i d = i d ;

}

p u b l i c v o i d run ( ) {w h i l e ( v a r p a r t . t e s t e ( i d ) ){

a f f i c h e ( ” Avant ”+v a r p a r t ) ;v a r p a r t . decremente ( i d ) ;a f f i c h e ( ” Apr e s ”+v a r p a r t ) ;t r y { s l e e p ( 0 , 0 ) ;}catch ( I n t e r r u p t e d E x c e p t i o n e ){a f f i c h e ( ” I n t e r r o m p u ” ) ;

}}a f f i c h e ( ” Termine ( ”+v a r p a r t+” ) ” ) ;}

v o i d a f f i c h e ( S t r i n g s ){System . out . p r i n t l n (

Thread . c u r r e n t T h r e a d ( ) . getName ()+” : ”+s ) ;}

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 ) {i n t n = 3 , v a l =9;

v a r p a r t = new E n t i e r P a r t a g e ( v a l ) ;f o r ( i n t i =1; i<=n ; i ++)

new V a r i a b l e P a r t a g e e B S ( i ) . s t a r t ( ) ;System . out . p r i n t l n ( ”Main : v a l e u r = ”+v a l ) ;System . out . p r i n t l n ( ”Main : I l y a”+n+” t h r e a d s , ”

+” l a r e g l e du j e u e s t chaque t h r e a d ne ” ) ;System . out . p r i n t l n ( ”Main : peut r e t i r e r qu ’ un”

+” nombre de p o i n t s e g a l e a son i d e n t i t e .\n” ) ;}

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Problemes de Coexistence

L’existence de plusieurs activites au sein d’un memeenvironnement induit necessairement des problemes de

ordonnancement =⇒non-determinisme desexecutionspartage des donnees

visibilite des donneessynchronisation des actions sur ces donnees

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Conclusion ProvisoireLa programmation multi-thread est delicate :

non-determinisme,variables partagee et synchronisation,optimisations provoquant des comportementsparfois non intuitifs,portabilite vs utilisation des ressources natives,variations dans l’implementation des machinesvirtuelles,erreurs ne se revelant que sous hautes charges (ie enproduction)...

Methodologie particuliere a suivre en utilisant lesnombreuses primitives de synchronisation (apparuesdepuis la version 1.5).

Arnaud Labourel, arnaud.labourel@lif.univ-mrs.fr Les threads en Java

Recommended