Le multitâche en Java
Transcription
Le multitâche en Java
Le multitâche en Java Premier Cycle Cours EURINSA 2002 (c) P.Pollet 05/12/2002 Java 2001 (PP) 1 Plan ◆ Définition des threads ◆ Créer un thread ◆ Le problème de la synchronisation ◆ Les signaux ◆ Exemple I: Producteurs et Consommateurs ◆ Exemple II: Animation d ’applettes 05/12/2002 Java 2001 (PP) 2 Définition des threads ◆ La machine virtuelle JVM permet l ’exécution concurrente de plusieurs processus dans un même programme. ◆ Un processus est un objet sous-classe de java.lang.Thread qui possède: – – – – une instruction courante un environnement (ses variables d ’instance) un état (créé, actif, endormi,en attente, inactif, mort…) un nom ◆ Les Thread communiquent entre eux par des signaux (wait(), notify()). ◆ Les Thread doivent rendre la main à la JVM par leurs méthodes sleep(), yield() ou suspend() (multitâche coopératif). ◆ Les threads peuvent avoir des priorités différentes. 05/12/2002 Java 2001 (PP) 3 Créer un thread ◆ Deux façons de créer un Thread: ◆ Sous-classer java.lang.Thread en redéfinissant au moins la méthode run(). Class MonThread extends Thread { public void run() { ……. } } Méthode la plus simple. ◆ Implémenter l ’interface java.lang.Runnable et implémenter run() Class MaClasse extends SonAncetre implements Runnable { Thread monThread; // à créer et à lancer dans un constructeur ou init() public void run() { ……. Méthode obligatoire si une super-classe } est requise (applette). } 05/12/2002 Java 2001 (PP) 4 Etendre Thread ◆ L ’appel à start() enregistre le Thread auprès de la JVM et appelle la méthode run() redéfinie qui réalise le travail. ◆ Le Thread meurt automatiquement si la méthode run() se termine. class Producteur extends Thread { Producteur (….) { // un éventuel constructeur super(); …. Forme standard: } Ne pas oublier d ’appeler public void run () { sleep(), wait(), suspend(), yield()... while (true) {…………} } } Producteur p1=new Producteur (….); p1.start(); Producteur p2=new Producteur(…..); p2.start(); 05/12/2002 Java 2001 (PP) 5 Implémenter Runnable ◆ Obligatoire sur la classe a une superclasse (pas d ’héritage multiple en Java) class Producteur extends SuperClasse implements Runnable { public Thread monThread; Producteur (….) { // un constructeur obligatoire pour créer le processus super(...); …. monThread=new Thread(this); Notez le this pour associer } le Thread à cette classe. public void run () { Même code que dans le cas while (true) {…………} précédent (sleep(),.... } } Producteur p1=new Producteur (….); p1.monThread.start(); Producteur p2=new Producteur(…..); p2.monThread.start(); 05/12/2002 Java 2001 (PP) 6 Le problème de la synchronisation ◆ Tous les processus accèdent aux ressources publiques du programme (instances d ’objets, variables, fichiers…). ◆ Il faut mettre en place un accès exclusif pendant l ’exécution d un bloc d’instructions. ◆ Exemple: –un processus dessine des points (en 4 instructions) alors qu’un second les déplace (en 2 instructions). Il faut garantir que ces instructions ne seront pas interrompues ! ◆ Mot clé synchronized: –Permet de gérer les accès concurrents sur –une méthode : –une classe : –un bloc: public synchronized maMethode() {……} synchronized (monObjet) { monObjet.saMethode();} synchronized (unTruc) { // manipule unTruc....} –on définit ainsi une section critique avec mise en attente automatique par la JVM des autres processus. 05/12/2002 Java 2001 (PP) 7 Les signaux ◆ Toutes les classes Java héritent de Object et disposent donc d ’un moniteur d ’accès à travers wait() et notify(). ◆ Lorsqu’un processus accède à un objet il peut appeler la méthode wait() de cet objet. (monObjet.wait()) • Relâche l ’accès à l ’objet et s ’endort. • attend une notification des autres processus. • redémarre dès qu’il obtient à nouveau l’accès exclusif ◆ Lorsqu ’un processus a «fini » avec un objet, il appelle sa méthode notify (). (monObjet.notify()). • Signale aux processus qui ont fait un wait, qu’ils peuvent se réveiller. • Ne relâche pas l ’accès (=>à faire en fin de bloc synchronisé). • Ne peut se faire que si on a eu l ’accès (dans un bloc synchronisé) ◆ Permet une synchronisation de type Producteur-Consommateur. 05/12/2002 Java 2001 (PP) 8 Exemple I: un producteur de nombres ◆ Dépose dans un tableau de taille limitée des nombres qui sont pris par des consommateurs. class Producteur extends Thread { Une pause d ’une seconde public void run () { while (true){ try {sleep (1000);} catch (InterruptedException e) {}; synchronized (table) { Section critique if (table.estPleine()) try {table.wait();} catch (InterruptedException e) {}; table.ajoute((int)( Math.random()*1000)); table.notify(); Attente si table est pleine } } } Signale aux consommateurs et aux autres producteurs (!) de se réveiller... 05/12/2002 Java 2001 (PP) 9 Exemple I: un consommateur de nombres ◆ Prends dans un tableau de taille limitée des nombres qui y sont placés par des producteurs. class Consommateur extends Thread { Une pause d ’une seconde public void run () { while (true){ try {sleep (1000);} catch (InterruptedException e) {}; synchronized (table) { Section critique if (table.estVide()) try {table.wait();} catch (InterruptedException e) {}; System.out.println (table.retire()); table.notify(); Attente si table est vide } } } Signale aux producteurs et aux autres consommateurs (!) de se réveiller... 05/12/2002 Java 2001 (PP) 10 Exemple II: Animation dans une applette. ◆ Un Thread dessinateur dessine des rectangles qui se déplacent dans leur propre processus: public class Animateur extends java.applet.Applet implements Runnable { RectangleMobile r1,r2,r3; Thread dessinateur; Une petite pause public void run () { entre chaque affichage while (true){ try {dessinateur.sleep (10);} catch (InterruptedException e) {} repaint(); Création de quatre processus: }} un pour le dessinateur et un public void paint(Graphics g) { pour chaque rectangle r1.paint(g); r2.paint(g);r3.paint(g);} public void start() { r1=new RectangleMobile (Color.red,50,50,5,5,100); r1.start(); r2=new RectangleMobile (Color.black,100,0,15,15,300); r2.start(); r3=new RectangleMobile (Color.blue, 0,100,25,25,200); r3.start(); dessinateur=new Thread(this); dessinateur.start(); }} 05/12/2002 Java 2001 (PP) 11 Exemple II: les rectangles mobiles. public class RectangleMobile extends Thread { Color c; int rx,ry,dx,dy,dt; RectangleMobile (Color c, int rx, int ry, int dx, int dy, int dt ) { this.c=c;this.rx=rx;this.ry=ry; this.dx=dx; this.dy=dy;this.dt=dt; } Une pause de dt public void run () { entre chaque mouvement while (true){ try {sleep (dt);} catch (InterruptedException e) {} Ne sort pas de l ’écran ! if ((rx+dx <0) || (rx+dx)>200) dx= -dx; if ((ry+dy <0) || (ry+dy)>200) dy= -dy; rx +=dx; ry +=dy;} } Section critique ! public synchronized void paint(Graphics g) { g.setColor( c);g.fillRect (rx,ry,30,30); } 05/12/2002} Java 2001 (PP) 12