COURS THREADING

Programming, Java, Multi-Threading · course

Voir tous les documents en programmation

COURS THREADING

JAVA

1

PROGRAMMATION « PARALLÈLE »

 Processus = unité fonctionnelle

Code

Données

Ressources

Système d’exploitation

• Un processus est une unité d’exécution qui possède son code, son espace mémoire et un accès à des ressources gérées par le système d’exploitation

• La vie d’un processus est gérée par d’exploitation

le système

 Exécution

Processus 1

Processus 2

Système d’exploitation

Temps CPU

• La communication entre les processus s’effectue par des mécanismes offerts par le système d’exploitation

2

Inconvénients d’un processus

Un processus est coûteux en mémoire (code

+ données)

Le partage des données entre processus est

difficile à réaliser

Le lancement d’un processus est relativement lent à cause de : Sa taille, La charge du système d’exploitation

Le partage de certaines ressources systèmes

est difficile, parfois impossible

Classiquement les programmes ne possèdent qu’un seul processus !

3

THREAD ET UTILITÉ DU MULTI-THREADING

Définition :

 Un Thread est un processus interne à un processus  Un processus comporte un ou plusieurs Threads  Les Threads d’un processus partagent son code, ses données et ses ressources mais peuvent aussi disposer de leurs données propres Les Threads d’un processus peuvent s’exécuter en parallèle (OS dépendant)

Avantages :

Légèreté (« light weight process » ou « processus léger ») grâce au partage des données (meilleures performances au lancement et en exécution) Partage des ressources systèmes du processus

Java est un langage multi-Thread , cette qualité dépend du support des Threads et du multi-Threading du système d’exploitation

4

LA CLASSE JAVA.LANG.THREAD

 La classe Thread est la classe d’implémentation d’un Thread

 Elle dispose de l’ensemble des services de

gestion d’un Thread :

Création et destruction Gestion de l’état Synchronisation

    …

 Pour bénéficier du multi-Threading, il y a deux

utilisations possibles :

1.

Sous-classer Thread car toute instance d’une sous-classe de Thread est un Thread 2. Définir une association entre la classe à

utiliser et la classe Thread

5

SOLUTION 1: SOUS-CLASSER THREAD

 Exemple : class ActionDeCuisine extends Thread { private String afaire ; public ActionDeCuisine(String afaire) { this.afaire = afaire ; } public void run ( ) { for (int i=0 ; i<2 ; i++) System.out.println(afaire) ;} } class Recette { public static void main(String[ ] args) { ActionDeCuisine a1 = new ActionDeCuisine("Battre les

œufs");

ActionDeCuisine a2 = new ActionDeCuisine("Faire

Publicité

fondre le

Chocolat"); ActionDeCuisine a3 = new ActionDeCuisine("Ajouter

du sucre"); a1.start ( ) ; a2.start ( ) ; a3.start ( ) ; } }

6

RÉSULTAT

Le résultat exact de cet exemple dépend du système

d'exploitation.

Résultats possibles : Battre les œufs Faire fondre le chocolat Ajouter du sucre

Battre les œufs … Battre les œufs Faire

fondre

le chocolat

Battre les œufs Faire fondre le chocolat Ajouter du sucre

Faire fondre le chocolat Ajouter du sucre Ajouter du sucre

7

SOUS-CLASSER THREAD (SUITE)

La classe Thread

est la classe de base d’implémentation du multi-Threading dans Java. Sous–classer Thread permet de créer des classes d’objets qui pourront s’exécuter en parallèle

Les méthodes run ( ) et start ( ) :

 void start ( ) Permet de demander au Thread concerné de démarrer (asynchrone : cette fonction redonne immédiatement la main pour la suite des instructions).  void run ( ) Méthode à redéfinir pour décrire les actions le contenu de cette d'un Thread méthode qui représente les actions du Thread et qui sera donc exécuté après que le Thread aura été démarré par la méthode start( ) )

(c'est

8

PRINCIPE DE FONCTIONNEMENT

Un

système

d'exploitation multi-Thread affecte des tranches de temps à chaque Thread activable : il interrompt le Thread actif quand une tranche de temps est écoulée et passe le contrôle au Thread activable suivant. Le Thread initial ne reprendra donc la main que lorsque son tour reviendra, après que les autres Threads activables auront épuisé leur tranche de temps.

La durée des tranches de temps peut être très différente d'une machine à une autre, ce qui explique les différences de comportement d'un système à un autre.

9

SOLUTION 2: IMPLÉMENTER L’INTERFACE RUNNABLE

class ActionDeCuisine implements Runnable { private String afaire ; public ActionDeCuisine(String afaire) { this.afaire = afaire ; } public void run() {for (int i = 0 ; i<4 ; i++) System.out.println(afaire) ;} }

class Recette { public static void main(String[] args) { Thread a1 = new Thread (new ActionDeCuisine("Battre les

œufs")) ;

Thread a2 = new Thread (new ActionDeCuisine("Faire

fondre le Chocolat")) ;

Thread a3 = new Thread (new ActionDeCuisine(" Ajouter du

sucre")) ;

a1.start() ; a2.start() ; a3.start() ; } }

10

IMPLÉMENTER L’INTERFACE RUNNABLE (SUITE)

La classe Thread admet un constructeur qui prend en argument une instance de Runnable L’interface Runnable ne contient que la méthode run ( ) qui sera appelée lors du démarrage du Thread .

La classe qui contient le code a exécuter en l'interface

implémenter

doit

parallèle Runnable L’avantage

l’interface d’implémenter Runnable par une classe est que celle-ci peut étendre une autre classe au choix (puisque Java ne permet pas l’héritage multiple)

11

IMPLÉMENTER L’INTERFACE RUNNABLE (SUITE)

Remarques :

Lorsqu’on est dans le code de la méthode run ( ) , this retourne une référence sur l’objet dont la classe implémente Runnable (référence sur ActionDeCuisine). Si l’on veut récupérer une référence su le Thread lui-même il faut utiliser la méthode statique

static Thread currentThread ( )

la

de

On peut associer plusieurs Threads à une instance implémentant Runnable. Ils partagent tous les mêmes attributs de cette classe. Par contre toute variable créée dans la méthode run ( ) sera unique par Thread

Publicité

classe

12

CHOIX D’IMPLÉMENTATION D’UN THREAD

Sous-classer Thread Quand? Lorsque l’on ne nécessite pas une super-classe particulière,

ou que l’on a aucun besoin de partage contexte

class MaClasse extends Thread { … public void run ( ) {// redéfinition de run } … }

Utiliser Runnable Quand? Lorsque la super-classe est conceptuellement imposée

(exemple : Applet) ou qu’un partage de contexte est requis pour un nombre quelconque de Threads

class MaClasse extends Base implements Runnable { … public void run ( ) {// redéfinition de run } … }

13

LES ÉTATS D’UN THREAD

construction

start ( )

créé

actif

suspend ( )

sleep (…)

resume ( )

endormi

stop ( )

stop ( )

destruction

La méthode isAlive ( ) :

créé

actif

endormi mort

Retourne

false

true

true

false

14

LES ÉTATS D’UN THREAD (SUITE)

 Créé Un Thread est créé comme n’importe quel objet Java, par appel à un constructeur. Lors de cette étape aucune autre opération que la réservation mémoire n’est effectuée

 Actif Le Thread est dans cet état lorsque après la création, il est activé par start ( ) qui lance la méthode run ( ). Ou encore lorsqu’il est réactivé après s’être endormi. Il est alors ajouté à la liste des Threads actifs qui sont exécutés en temps partagé

 Endormi Un Thread peut être endormi et réactivé de plusieurs manières :

sleep (long millisecondes) throws

InterruptedException endort le Thread pendant l’intervalle de temps spécifié et le réveille lorsque ce temps est écoulé

suspend ( ) endort un Thread et resume ( ) pourra alors

le réactiver

 Mort

Quand la méthode run ( ) a terminé son exécution Par un appel explicite à stop ( )

15

PRIORITÉS

Principes

 Un Thread A qui a une priorité supérieure à celle d’un autre Thread B est exécuté avant B. Les Threads de même priorité se partagent le temps du processeur avec un ordre indéterminé (système d’exploitation dépendant) À sa création un processus a par défaut la même priorité que le processus qui lui a donné naissance Java offre la possibilité de fixer les priorités des différents Threads d’un exécutable

Méthodes de Thread

 void setPriority (int) : modifie la priorité du receveur en fonction du paramètre. Cette priorité doit être comprise entre [MIN_PRIORITY, MAX_PRIORITY]  int getPriority ( ) : permet de connaître la priorité d’un Thread Le niveau de priorité « normal » est donné par la constante public static final int NORM_PRIORITY

16

PRIORITÉS (SUITE)

Le partage de temps CPU entre Threads de même

priorité est totalement dépendant du système d’exploitation

Publicité

Deux types de gestion de la ressource CPU

existent : Time-slicing : La ressource CPU est partagée équitablement entre Threads de même priorité par le système d’exploitation Préemption: Le partage de la ressource CPU doit être géré explicitement par l’utilisateur

Le Thread courant cède la ressource CPU à un autre Thread de même priorité dans les cas suivants :

 Involontairement sur entrée-sortie  Implicitement sur passage à l’état endormi  Volontairement par appel à la méthode statique public static void yield ( ) courant de passer qui permet au Thread immédiatement la main aux autres. Cette méthode ne permet pas à un Thread de priorité inférieure de s’exécuter, seul un Thread de priorité égale peut prendre la main

17

LA MÉTHODE JOIN ( ) 1/2

Exemple : class ActionDeCuisine extends Thread { private String afaire ; public ActionDeCuisine(String afaire) { this.afaire = afaire ; } public void run ( ) { // le contenu du Thread for (int i=0 ; i<2 ; i++) { } } } class Recette { public static void main(String[ ] args) { ActionDeCuisine a1 = new ActionDeCuisine("Battre les

System.out.println(afaire) ;

œufs");

ActionDeCuisine a2 = new ActionDeCuisine("Faire fondre

le Chocolat");

ActionDeCuisine a3 = new ActionDeCuisine("Ajouter du

sucre");

a1.start() ; a2.start() ; a3.start() ; System.out.println("Mettre au four") ; } }

18

RÉSULTAT

Résultat : Mettre au four Battre les œufs Faire fondre le chocolat Ajouter du sucre Battre les œufs Faire fondre le chocolat Ajouter du sucre

19

LA MÉTHODE JOIN ( ) 2/2

public void join ( ) throws InterruptedException : bloque le thread en cours d’exécution jusqu’à ce qu’il termine son travail  Exemple modifié: class Recette { public static void main(String[] args) { ActionDeCuisine a1 = new ActionDeCuisine("Battre

les œufs");

ActionDeCuisine a2 = new ActionDeCuisine("Faire

fondre le Chocolat");

ActionDeCuisine a3 = newActionDeCuisine("Ajouter

du sucre"); a1.start( ) ; a2.start( ); a3.start( ) ; try {a1.join( ); a2.join( ); a3.join( ); } catch (InterruptedException e) { } System.out.println("Mettre au four") ; } }

20

RÉSULTAT

Résultat : Battre les œufs Faire fondre le chocolat Ajouter du sucre Battre les œufs Faire fondre le chocolat Ajouter du sucre Mettre au four

21

EXERCICE D’APPLICATION

22

CORRECTION

public void run (){

C[i][j]=0; for (int k= 0; k< B.length; k++){ C[i][j] += A[i][k]*B[k][j]; System.out.println ( getName()+ «travaille »);

}

}

23

LANCEMENT DES THREADS

// Lancement des threads

MonThread []tabThread = new MonThread [nbThread];

int k = 0; for (int i= 0; i< C.length; i++) { for (int j= 0; j< C[i].length; j++) { tabThread[k] = new MonThread (A, B, C, i, j); tabThread[k].setName ("Thread"+k); tabThread[k].start(); k++; }

24

AFFICHAGE DU RÉSULTAT

try { for (k= 0; k<nbThread; k++) tabThread[k].join(); }

catch (InterruptedException ee){}

System.out.println("\n Matrice C"); for (int i= 0; i< C.length; i++) { for (int j= 0; j< C[i].length; j++) { System.out.print(C[i][j]+ " "); } System.out.println(); }

25