Introduction à Java - les « Threads » -

Slides:



Advertisements
Présentations similaires
La programmation concurrente en Java
Advertisements

1 Swing par la pratique contrat Creative Commons Paternité-Pas d'Utilisation Commerciale-Partage des Conditions Initiales à l'Identique.
Gestion des événements (suite)
Programmation événementielle
NSY102 1 NSY102 Conception de logiciels Intranet Concurrence Notes de cours Cnam Paris jean-michel Douin, douin au cnam point fr 25 Février 2013.
La classe String Attention ce n’est pas un type de base. Il s'agit d'une classe défini dans l’API Java (Dans le package java.lang) String s="aaa"; // s.
TP 7.1 synchronized et join Écrire un programme Java qui crée 1000 threads et maintient un compteur nb du nombre de threads créés jusque-là. Le thread.
Arbres Un premier exemple Contenu Rendu Ecouteurs Parcours
Composants graphiques de Java
L’ interruption de boucle
Voisin-Polian : Introduction à Java 1 Introduction à Java - AWT - Frédéric VOISIN – Nicole POLIAN FIIFO - « Remise à Niveau »
Plan du cours 5:Threads introduction Définition Création des Threads
Faisons une interface réactive.
CURSUS DE FORMATION AUX NOUVELLES TECHNOLOGIES DE DEVELOPPEMENT UV Threads Module Java Expert.
Les entrées /sorties en Java François Bonneville
Connexion base de données
Chapitre IV Object, interfaces, classes imbriquées.
Injection de dépendances
Système d’Exploitation
BlueJ_XI 1 Java, les objets : tout de suite ! Gestion des erreurs : les exceptions Notes de cours associées au chapitre 11 tutorial BlueJ
Introduction à la programmation (420-PK2-SL) cours 12 Gestion des applications Technologie de linformation (LEA.BW)
Les méthodes en java Une méthode est un regroupement d’instructions ayant pour but de faire un traitement bien précis. Une méthode pour être utilisée.
POO-L3 H. Fauconnier1 Chapitre IV 1. classe Object, clonage 2. interfaces 3. classes internes et imbriquées.
Faculté I&C, Claude Petitpierre, André Maurer 1 Java.
1 1 Université Evry Val d'Essonne Y. Laborde Une calculatrice (sans MVC) fonctionnant sur la base d'un modèle en Java.
Langage Oriente Objet Cours 4.
Cours du 19 octobre. POO-L3 H. Fauconnier2 E) Constructeurs et héritage Le constructeurs ne sont pas des méthodes comme les autres: le redéfinition na.
Badr Benmammar Programmation concurrente et temps réel en Java Badr Benmammar
Master 1 SIGLIS java Lecteur Stéphane Tallard Chapitre 4 – Structures de contrôle.
77 Utilisation des classes (suite). 7-2 Objectifs A la fin de ce cours, vous serez capables de : Définir des méthodes surchargées dans une classe Fournir.
Classes abstraites et Interfaces
Interface graphiques.
NSY102 1 Concurrence compléments Notes de cours Cnam Paris jean-michel Douin, douin au cnam point fr 19 Mars 2007.
Le patron de conception « Strategy » Simon Durocher ( )
Programmation par Objets et Java
66 Utilisation des classes et des objets. 6-2 Objectifs A la fin de ce cours, vous serez capables de : Créer de nouvelles classes à laide de Eclipse Utiliser.
JUnit Présentation complète de JUnit et « guide d’utilisation » en 13 transparents.
Programmation concurrente
CSI2520, Hiver 2007 Programmation concurrente. CSI2520, Hiver 2007 Programmation concurrente La programmation est distribuée lorsque les processus ne.
POO-L3 H. Fauconnier1 Supplément gratuit…. POO-L3 H. Fauconnier2 Entrée-sortie public static void main(String[] args) { // sortie avec printf ou double.
Design Pattern: Decorator
Faculté I&C, Claude Petitpierre, André Maurer 1 Concepts dhéritage Héritage dimplémentation hasA Héritage de spécialisation isA.
Faculté I&C, Claude Petitpierre, André Maurer Le parallélisme Introduction.
Multi-Thread Jian-Yun Nie
PROGRAMMATION MULTI-TÂCHES (MULTITHREADING)
1 IFT 6800 Atelier en Technologies dinformation Le langage de programmation Java chapitre 3 : Classes et Objects.
Badr Benmammar Formation Développeur Java Thread et Swing Badr Benmammar
Formation Développeur Java Applet et interfaces graphiques avec AWT
Badr Benmammar Programmation concurrente et temps réel en Java Badr Benmammar
Java Swing.
Cours 11 Threads. Chapitre X threads threadPOO-L3 H. Fauconnier3 Threads threads: plusieurs activités qui coexistent et partagent des données exemples:
Cours 6 décembre. Collections POO-L3 H. Fauconnier3 Collections types de données interfaces implémentations algorithmes Interfaces:
Cours 5 Héritage, Interfaces, classes internes. POO-L3 H. Fauconnier2 La classe Object Toutes les classes héritent de la classe Object Object méthodes:
jean-michel Douin, douin au cnam point fr
COURS DE PROGRAMMATION ORIENTEE OBJET :
LIFI-Java 2004 Séance du Mercredi 22 sept. Cours 3.
11/04/ L'héritage Cours 7 Cours 7.
Cours 7 Classes locales Clonage Divers: tableaux.
Interfaces graphiques. Composants d'interface utilisateur graphique (GUI) 1 Bibliothèques Awt et Swing Procédures communes pour l'utilisation de ces clases.
14 La gestion d’événements
Tutorat en bio-informatique
Constructeurs H Batatia. Variable statique Une variable statique est partagée par tous les objets d’une classe.
Programmation Système et Réseau
Les classes présenté par: RAHMOUNE RIME / ZEKRI SELMA.
Cours du 5 novembre.
Héritage H. Batatia. plan Notion (que signifie l’héritage) Ecriture en java Héritage multiple (interdit) Instanciation (partie propre et partie héritée)
Cours 4 (14 octobre) Héritage. Chapitre III Héritage.
Introduction à la programmation objet avec java
Java Swing. Principes de base  Des composants graphiques (exemple: JFrame, JButton …)  Hiérarchie de classes  Des événements et les actions à effectuer.
Frédéric Le Mouël, Stéphane Frénot, Frédérique Laforest, Tarak Chaari – Dpt TC JAV 1 JAV – TD 8 Les threads en Java.
Transcription de la présentation:

Introduction à Java - les « Threads » - Frédéric VOISIN – Nicole POLIAN FIIFO - « Remise à Niveau »

Les « Threads » Java (ou « processus légers ») Ils permettent de lancer plusieurs tâches en même temps au sein d’un même processus Ils permettent de refléter des découpages logiques en composants s’exécutant indépendamment ou en coopération Ils sont utilisés en interne par Java : le ramasse-miette est un thread de faible priorité, la méthode main(String[] args) s’exécute dans un thread … Les threads partagent la même zone mémoire, ce qui facilite la communication entre threads. Le temps de commutation entre threads est inférieur à celui des processus.

Exemple (presque) sans thread public class Train { int vitesse; String nom; public Train(int v, String n){ vitesse = v; nom = n;} public void run() { System.out.println(nom + " part"); try { Thread.currentThread().sleep(vitesse*500); } catch (InterruptedException e) {} System.out.println(nom + " roule"); Thread.currentThread().sleep(vitesse*50); System.out.println(nom + " s'arrete"); } La méthode main s’exécute dans un thread ! Le déroulement de sleep pourrait être abrégé par une « interruption », d’où le try/catch

Exemple sans thread (suite) // lancement de trois trains de vitesses différentes public class TestTrain { public static void main (String[] args) { Train micheline = new Train(50, "MICHELINE"); Train tgv = new Train(10, "TGV"); Train corail = new Train(20, "CORAIL"); micheline.run(); tgv.run (); corail.run(); System.out.println("fin du main"); } MICHELINE part MICHELINE roule MICHELINE s'arrete TGV part TGV roule TGV s'arrete CORAIL part CORAIL roule CORAIL s'arrete fin du main

Exemple avec thread public class Test { public static void main(String[] args) { Train tgv = new Train(10, "TGV"); Train corail = new Train(20,"CORAIL"); Train micheline = new train (50, "MICHELINE"); micheline.start(); tgv.start(); corail.start(); System.out.println("Threads actifs : " + Thread.currentThread().activeCount()); try { corail.join(); // attendre la fin de corail ! } catch (InterruptedException ex) { } System.out.println("fin du main"); }

Exemple avec thread (suite) class Train extends Thread { int vitesse; public Train(int v, String n) { super(n); // permet de « nommer » le thread. // getName() renvoie le nom ! vitesse = v; } public void run() { System.out.println(getName() + " part"); try { sleep(vitesse*500); } catch(InterruptedException e) { } System.out.println(getName() + " roule"); try { sleep(vitesse*50); System.out.println(getName() + " s'arrete"); Exemple d’exécution Threads actifs : 4 MICHELINE part TGV part CORAIL part TGV roule TGV s'arrete CORAIL roule CORAIL s'arrete Threads actifs : 2 fin du main MICHELINE roule MICHELINE s'arrete

Le principe des Threads La classe Train dérive de la classe Thread. La méthode start démarre le thread, ce qui entraîne l’appel de la méthode run. Le thread termine quand il atteint la fin de la méthode run. La méthode join permet de se synchroniser avec la fin d’un thread. Une autre synchronisation serait nécessaire si le thread produisait des résultats à récupérer (à voir après) L’héritage multiple n’existant pas en Java, il existe un deuxième mécanisme pour utiliser les threads : l’utilisation de l’interface Runnable, qui impose l’existence d’une méthode run. On passe alors une instance d’une classe qui implémente Runnable comme premier argument au constructeur de Thread.

Utilisation de l’interface Runnable public class Test { public static void main(String[] args) { Thread tgv = new Thread(new Train(10, "TGV")); Thread corail = new Thread(new Train(20, "CORAIL")); Thread micheline = new Thread(new Train(50, "MICHELINE")); micheline.start(); tgv.start(); corail.start(); System.out.println("fin du main") ; } // le paramètre du constructeur de Thread doit implémenter l’interface Runnable !

Utilisation de l’interface Runnable (suite) public class Train implements Runnable { int v; String nom; public Train(int i, String n) { v = i; nom = n;} public void run() { System.out.println(nom + " part"); try { Thread.currentThread().sleep(v*500); } catch(InterruptedException e) {} System.out.println(nom + " roule"); Thread.currentThread().sleep(v*50); System.out.println(nom + " s'arrete"); } fin du main MICHELINE part TGV part CORAIL part TGV roule TGV s'arrete CORAIL roule CORAIL s'arrete MICHELINE roule MICHELINE s'arrete

Les états d’un Thread new ( ) créé start ( ) wait ( ) ou sleep ( ) actif En attente mort new ( ) terminaison start ( ) wait ( ) ou sleep ( ) notify ( ) ou interruption

Les principales méthodes liées aux threads statiques : currentThread() activeCount() // threads démarrés et pas encore morts enumerate() // permet de les copier dans un tableau // Thread[] th=new Thread[nb];nb=Thread.enumerate(th); yield() // rend la main volontairement pour un autre thread sleep() // ne relâche pas les moniteurs (cf. infra) non statiques isAlive() join() setDaemon() // à faire avant start() ! isDaemon() dans Object // pour les moniteurs (synchronisation de threads) wait // en attente de notification notify // notification « Deprecated » (induisent de forts risques de deadlock, cf. infra) stop, suspend, resume

Exemple de Thread public class Heure1 extends Frame { // utilisation de AWT !! Label l1, l2, h1, h2; Button arret1; Timer1 t1, t2; Heure1() { setLayout(new FlowLayout()); l1 = new Label (" "); l2 = new Label (" "); l1.setBackground(Color.white); l2.setBackground(Color.white); l1.setAlignment(Label.CENTER); l2.setAlignment(Label.CENTER); Font f = new Font("TimesRoman", Font.PLAIN, 18); setFont(f); arret1 = new Button ("STOP"); h1 = new Label("MONTREAL"); h2 = new Label("PARIS"); ActionListener larret1 = new ActionListener() { public void actionPerformed(ActionEvent e){ System.exit(1);} }; // classe interne, définie au vol ! … // ActionListener est une interface associée aux événements click sur les boutons

Exemple de Thread (suite) arret1.addActionListener(larret1); // associe action/bouton add(arret1); // ajout des composants add(l1); add(h1); // à l’instance de Frame add(l2); add(h2); t1 = new Timer1(l1, 1); t2 = new Timer1(l2, 2); t1.start(); t2.start(); } // fin de Heure1() public static void main(String[] args) { Heure1 t = new Heure1(); t.setBounds(20, 20, 800, 60); t.setVisible(true); }

Exemple de Thread (suite) public class Timer1 extends Thread { Label l; int type; Date maDate; SimpleDateFormat mF = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss"); public Timer1(Label l, int t) { this.l = l; type = t; } public void run() { while (true) { try { sleep (2000); } catch(InterruptedException e) {} maDate = new Date(); if (type == 1) { mF.setTimeZone(TimeZone.getTimeZone("America/Montreal")); L.setText(mF.format(maDate)); } else { mF.setTimeZone(TimeZone.getTimeZone("Europe/Paris")); }

Les démons (« daemon ») Il existe deux sortes de threads deux méthodes les threads ordinaires (utilisateurs) les threads démons (notamment créés par la JVM; exemple : le ramasse-miettes) deux méthodes setDaemon(boolean b) // à exécuter avant start boolean isDaemon() Un « processus » Java s’arrête lorsqu’il ne reste plus que des threads démons. Ceux-ci correspondent à des threads « de service » qui ne contribuent pas directement à la logique applicative.

L’ordonnancement (scheduling) Question : quel thread a la main ? celui qui a la plus grande priorité parmi les threads actifs ! pour changer la priorité : getPriority() setPriority() Thread.MIN_PRIORITY Thread.MAX_PRIORITY Thread.NORM_PRIORITY En cas d’égalité, certaines implémentation laissent la main au thread en cours (pas d’équité entre les threads potentiellement activables). Dans ce cas, il faut utiliser la méthode yield() ou bien sleep(0) pour relâcher la main.

Arrêter un Thread } // accès sans précaution à arrete ;-( public class TestArret { public static void main(String[] args) { tt = new Train(); tt.start(); try { Thread.currentThread().sleep(2000); tt.stoppe(); tt.join(); } catch (InterruptedException ex) {} System.out.println("fin du main"); } class Train extends Thread { private boolean arrete = false; public void run() { while (! arrete) { System.out.println("le train roule"); try { sleep(500);} catch(InterruptedException e) {} System.out.println("le train s'arrete"); public void stoppe() { arrete = true ; } } // accès sans précaution à arrete ;-( le train roule le train s'arrete fin du main

Problèmes de synchronisation Les threads partagent les mêmes données et agissent sur les mêmes objets  problèmes d’accès incohérents aux données On peut protéger une suite d’instruction (ou une fonction) avec synchronized Pour une fonction : à tout instant il s’exécute au plus une fonction synchronized sur un objet donné… mais les fonctions non synchronized n’ont aucune obligation  synchronized int fonct() { … } Par « verrouillage » d’un objet (arbitraire) pour une suite d’instructions arbitraire : synchronized (obj) { // au plus une séquence d’instructions ou méthode // synchronized à la fois sur obj. obj.action(); … Reprend les principes des moniteurs de Hoare/Brinch Hansen

Exemple de synchronisation class Truc { int val = 0; void incr(int tempo) { int i = val; try { Thread.currentThread().sleep(tempo); } catch (InterruptedException e) {} val = i+1; // la valeur de val il y a un certain temps ! try { Thread.currentThread().sleep(tempo) ; } catch (InterruptedException ex) { } ; } public String toString() { return "valeur " + val;}} class Collision { static truc cpt = new truc(); public static void main(String[] arg) { Compteur t1 = new Compteur(cpt,1); Compteur t2 = new Compteur(cpt,2); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException ex) {}; System.out.println("fin du main : " + cpt); }}

Exemple de synchronisation (suite) class Compteur extends Thread { int num; truc cpt; Random rd; public Compteur (truc c, int nm) { num = nm; cpt = c; rd = new Random(nm); } public void run() { System.out.println("debut run " + num); for(int i = 0; i<100; i++) { // synchronized(cpt) { cpt.incr(Math.abs(rd.nextInt())); System.out.println ("fin run " + num); sans synchronized(cpt) debut run 1 debut run 2 fin run 1 fin run 2 fin du main : valeur 143 avec synchronized(cpt) fin du main : valeur 200

Les appels wait et notify wait bloque l’exécution du thread jusqu’à réception d’une « notification » envoyée par un autre thread. Le verrou sur l’objet est levé (à la différence de sleep !) notify envoie la notification précédente : « réveil » du (ou plutôt d’un) thread bloqué. notifyAll() réveille tous les threads bloqués sur cet objet. Attention: les threads débloqués doivent encore « acquérir » l’objet sur lequel ils se synchronisent. Ils sont en concurrence avec tous les autres threads similaires (pas de privilège d’accès). Souvent on doit englober le wait dans une boucle d’accès en attendant qu’une certaine condition soit effectivement réalisée. Attention aux deadlocks, si on acquiert les objets dans le désordre ou si on oublie d’en libérer l’accès !

wait et notify (suite) synchronized ( obj ) { obj.wait ( ) ; } obj.notify ( ) ; T1 . . T2 . . . . . réveil L’attente se fait « sur »  un objet. Le notify est envoyé à ce même objet. L’objet doit « appartenir » au thread qui exécute wait/notify, cela implique l’utilisation obligatoire de synchronized. Gérer le verrou sur un objet nécessite d’acquérir cet objet !

Un Exemple … public class Heure2 extends Frame { Label l1, l2; Button h1, h2, arret1; Timer2 t1, t2; Heure2() { setLayout(new FlowLayout()); l1 = new Label(" "); l2 = new Label(" "); l1.setBackground(Color.white); l2.setBackground(Color.white); l1.setAlignment(Label.CENTER); l2.setAlignment(Label.CENTER); Font f = new Font("TimesRoman", Font.PLAIN, 18); setFont(f); arret1 = new Button("Stop Montreal"); h1 = new Button("MONTREAL"); h2 = new Button("PARIS"); ActionListener larret1 = new ActionListener() { public void actionPerformed(ActionEvent e) { t1.stoppe(); // arret definitif de l'horloge locale remove(l1); remove(h1); remove(arret); }}; …

Un Exemple (suite) ActionListener lh2 = new ActionListener() { public void actionPerformed(ActionEvent e) { if (! t2.isAlive()) { t2.start(); } }} ; ActionListener lh1 = new ActionListener() { if (! t1.isAlive()) { t1.start(); } else { t1.bascule(); } }}; arret1.addActionListener(larret1); h1.addActionListener(lh1; h2.addActionListener(lh2); add(arret1); add(l1); add(h1); add(l2); add(h2); t1 = new Timer2(l1, 1); t2 = new Timer2(lab2, 2); } public static void main(String[] arg) { Heure2 t = new Heure2(); t.setBounds(20, 20, 800, 60); t.setVisible(true);

Un Exemple (suite) class Timer2 extends Thread { Label L; int type; boolean marche, actif; public Timer2(Label l, int t) { L = l; type = t; marche = true; actif = true; } public void stoppe() { marche = false; } public void bascule() { if (actif) { actif = false ; } else { synchronized(L) { L.notify(); } } }

Un Exemple (suite) public void run() { Date maDate; SimpleDateFormat mF=new SimpleDateFormat("dd-MMM-yyyyHH:mm:ss"); while (marche) { try { sleep (2000); } catch (InterruptedException ex) {} if (! actif) { try { synchronized(L) { L.wait(); } } catch (InterruptedException ex) {} actif = true ; } maDate = new Date(); if (type == 1){ mF.setTimeZone(TimeZone.getTimeZone("America/Montreal")); L.setText(monFormat.format(maDate)); } else { mF.setTimeZone(TimeZone.getTimeZone("Europe/Paris")); L.setText(mF.format(maDate)); } }}}

Un Exemple (affichage)