Faisons une interface réactive.

Slides:



Advertisements
Présentations similaires
La programmation orientée objet avec Java L3-MIAGE Plan
Advertisements

Réaliser en Java un programme client d’une Base de Données
PHP5 its a kind of magic. Chargement automatique function __autoload( $nom_classe ) { require_once('obj/'.$nom_classe.'.class.php'); } si on exécute le.
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
Au programme du jour …. Ce que vous navez pas encore vu Constantes et variables de classe Main et Tests Utilisation de lAPI Existence des packages Existence.
SI3 MAM3 Hydro Nathan Cohen Igor Litovsky Christophe Papazian
Introduction à la Programmation Orientée Objet Retour sur les principaux concepts SI3 MAM3 Hydro Nathan Cohen
Formation C débutant. Notion de compilation source.c executable Phase de compilation Fichier de texte brut, inexploitable directement par la machine Fichier.
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
Page 1 Les applets Jacques Lonchamp. Page 2 Présentation Une applet est téléchargée à partir dune machine distante qui fournit le code. Ce chargement.
(Classes prédéfinies – API Java)
Introduction à Java - les « Threads » -
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
PHP5 its a kind of magic. Chargement automatique function __autoload( $nom_classe ) { require_once('obj/'.$nom_classe.'.class.php'); } si on exécute le.
CURSUS DE FORMATION AUX NOUVELLES TECHNOLOGIES DE DEVELOPPEMENT UV Threads Module Java Expert.
Windows XP Professionnel
Windows XP Professionnel
Introduction – Le bureau La visualisation des dossiers et des fichiers La gestion des dossiers et des fichiers Création dun nouveau dossier (méthode 1)
Les entrées /sorties en Java François Bonneville
Connexion base de données
Chapitre IV Object, interfaces, classes imbriquées.
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.
Faculté I&C, Claude Petitpierre, André Maurer 1 Java.
© 2007 P. Van Roy. All rights reserved. 1 FSAB1402: Informatique 2 La Concurrence Déclarative Peter Van Roy Département dIngénierie Informatique, UCL
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.
La programmation objet Illustration de la POO en Pascal
Master 1 SIGLIS java Lecteur Stéphane Tallard Chapitre 4 – Structures de contrôle.
Introduction au paradigme objet Concepts importants surcharge (overload) redéfinition (override) Définition d’une classe Définition des attributs.
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
Historique de SystemC Regroupe 4 courants didées: SCENIC Project : Synopsys+UC Irvine Philips System-Level Data Types, VSIA SLD DWG IMEC, Hardware-Software.
Interface graphiques.
NSY102 1 Concurrence compléments Notes de cours Cnam Paris jean-michel Douin, douin au cnam point fr 19 Mars 2007.
Graphical User Interface (GUI)
Programmation par Objets et Java
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.
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.
Exceptions IFT1025: Programmation 2 Jian-Yun Nie.
LIFI-Java 2004 Séance du Jeudi 9 sept. Cours 1. La notion de langage Décrire une tâche à effectuer –programme Écrire à un haut niveau –facile pour lutilisateur.
Badr Benmammar Formation Développeur Java Thread et Swing Badr Benmammar
Formation Développeur Java Applet et interfaces graphiques avec AWT
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 DE PROGRAMMATION ORIENTEE OBJET :
CSI1502 Principes fondamentaux en conception des logiciels Chapter 8: Gestion des exceptions.
Android UIThread, Thread, Handler et AsyncTask
4 Introduction des objets. Les chaînes et tableaux
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.
Tutorat en bio-informatique
Programmation Système et Réseau
Cours LCS N°4 Présenté par Mr: LALLALI
Pthread Ordonnancement. #define _MULTI_THREADED #include #ifndef _CHECK_H #define _CHECK_H /* headers used by a majority of the example program */ #include.
Héritage Conception par Objet et programmation Java
Transcription de la présentation:

Programmation Objet en JAVA Cours 8 Thread, Multi-thread, synchronisation, ...

Faisons une interface réactive. Réaliser l'éditeur simple permettant : visualiser l'heure (en temps réel ! ) insérer la date et l'heure automatiquement éditer le texte et, sauver le texte. Une fenêtre 3 boutons 1 action par bouton Zone d'affichage zone de texte « éditable » sur plusieurs lignes

Hiérarchie « graphique » simple

Hiérarchie « graphique » plus générique

Implémentation de l'éditeur simple - V1 L'application hérite d'une JFrame. Le constructeur prend en charge l'initialisation propre de l'interface. La « montre » dans sa version graphique nécessite l'implémentation d'une classe MontreG : héritage d'un JLabel + méthode de mise à jour de l'heure. En attributs, les composants nécessaires : 3 x JButton + 1 x JTextArea + 1 x MontreG. Implémenter les « ActionListener » correspondant aux boutons tels qu'ils puissent accéder à l'heure et l'insérer dans la zone de texte : sous forme de classes internes, ou l'application implements MouseListener, ou Créer une classe regroupant les actions (prévoir les accès et modifications public des attributs ).

La classe MontreG import java.awt.*; import java.awt.event.*; import javax.swing.*; public class MontreG extends JLabel{ public MontreG(){ super("Press start to get time"); }; public void go(){ while (true) { try { Thread.sleep(1000); } catch(InterruptedException e) { System.err.println("Interrupted"); } this.setText(new java.util.Date().toString()); public static void main(String[] args) {...}

La classe de l'application (résumé) import java.awt.*; import java.awt.event.*; import javax.swing.*; public class EdMontreBof extends JFrame { /* Les attributs sont les composants graphiques */ private MontreG montre; private JTextArea editor; private JButton startB; private JButton printB; private JButton saveB; /* Définition des ActionListener en classes internes */ class StartL implements ActionListener { ... } class PrintL implements ActionListener { ... } class SaveL implements ActionListener { ... } /* Le constructeur qui initialise tout */ public EdMontreBof(){...} public static void main(String[] args) { EdMontreBof edm = new EdMontreBof(); }

La classe de l'application : le constructeur public EdMontreBof(){ super("Pourquoi ?"); this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE ) ; this.setSize (250,200) ; /* Construction des composants*/ montre = new MontreG(); startB = new JButton("Start date");// mettre en route la montre printB = new JButton("Print date");// Recopier l'heure dans l'éditeur saveB = new JButton("Save"); startB.addActionListener(new StartL()); printB.addActionListener(new PrintL()); // ... pareil pour saveB editor = new JTextArea(5,20); JScrollPane scrollPane = new JScrollPane(editor, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); /* Ajout des composants au container */ Container cp = this.getContentPane(); cp.setLayout(new FlowLayout()); cp.add(montre); cp.add(startB); cp.add(printB); ... // pareil pour saveB cp.add(scrollPane); this.setVisible(true); }

le constructeur pour l'interface plus complexe public BigEd(){ /* Construction des «feuilles» : pareil */ ... /* Construction des panels */ left = new JPanel(); right = new JPanel(); /* Construction des composants : pareil */ /* Gestion des events : pareil */ /* Panel de gauche */ left.setLayout(new BoxLayout(left, BoxLayout.PAGE_AXIS)); left.add(montre); left.add(startB); left.add(printB); left.add(saveB); left.setBackground(Color.RED); /* Pour la droite */ right.add(scrollPane); /* Ajout des composants */ Container cp = this.getContentPane(); cp.setLayout(new BorderLayout()); cp.add(left,BorderLayout.WEST); cp.add(right,BorderLayout.EAST); this.setVisible(true); }

Retour à l'application simple : les ActionListeners public class EdMontreBof extends JFrame { .... le reste de la classe .... /* Les classes internes ainsi définis ont accès aux attributs et méthodes de la classe EdMontreBof (même privés !).*/ class StartL implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("Start"); go(); } class PrintL implements ActionListener { System.out.println("Print"); editor.append("\n"+montre.getText()+ " : ");

Les ActionListeners en classes anonymes dans le constructeur public EdMontreBof(){ ... printB = new JButton("Print date"); ActionListener pl = new ActionListener(){ public void actionPerformed(ActionEvent e) { System.out.println("Print"); editor.append("\n"+montre.getText()+ " : "); } }; printB.addActionListener(pl); // l’equivalent en plus laid : startB = new JButton("Start date"); startB.addActionListener(new ActionListener(){ System.out.println("Start"); go(); });

Que se passe-t-il ? Tout va bien, jusqu'au moment où la montre est lancée. Tout est bloqué, il est même impossible de fermer la fenêtre.

Pour aujourd’hui Collection (suite et fin) Retour sur la serialisation Classes internes et interfaces graphiques Thread Projet

La solution : les threads Faire en sorte que la montre « tourne » indépendamment de l'application : faire du multi-tâche. Pour résumer : Un ordinateur est une machine à exécuter pas à pas un programme. Un programme est une suite d’instructions, son exécution donne lieux à un processus A un moment donné l’ordinateur exécute une et une seule instruction Lorsqu’il y a plusieurs processus : l’ordenanceur répartit le temps de CPU pour chacun. un processus, c'est un PID, un espace mémoire indépendant, un espace d'adressage, un compteur ordinal, ... . Gérer par l'OS. En java, il existe des processus « légers » créer par la JVM : les Threads. Un thread est un « fil » d'exécution, un « sous-processus » Un programme java multi-thread : au sein du même processus (java) plusieurs fils d’exécution s’exécutent « en parallèle ». L’ordenanceur répartit le temps de CPU entre les processus et les threads.

Ordenancement : 2 processus

Ordenancement : processus et thread

Les threads en Java Il existe toujours un premier thread qui commence à exécuter la fonction main() Dans les interfaces graphiques Il existe un autre thread qui attend les actions de l’utilisateur et déclenche les écouteurs Il existe un autre thread qui redessine les composants graphiques qui ont besoin de l’être On peut créer ses propres threads

La classe Thread et l'interface runnable La création d'un thread passe par la création d'un objet de la classe java.lang.Thread. Un objet de type Thread représente la télécommande d’un thread réel Il sert à le manipuler (contrôle, priorité, synchronisation) Il faut indiquer au thread quelle méthode exécuter (mais pointeur sur méthode ?) :  faire un run de quoi ? Créons un objet qui soit « runnable », il servira de cible au thread. Un objet runnable est un objet qui implémente l'interface Runnable. public interface Runnable { public void run(); } La méthode run est la liste des tâches d’un thread, son « main ». Tout thread débute dans la vie par l'exécution d'une méthode run().

Création et démarrage - 1 Une fois créer, un thread ne fait rien tant qu'il n'a pas commencer : start(). start() lance l' exécution de run(). Une fois lancer, un thread va jusqu'au bout de run(), du moins tant qu'on ne le stop pas : stop(). class Animation implements Runnable { ... public void run() { while ( true ) { // Draw Frames repaint(); } Une première manière, pas très objet. Animation happy = new Animation("Mr. Happy"); Thread myThread = new Thread( happy ); // Jusqu'ici rien n'est lancé ! myThread.start();

Création et démarrage - 2 Il est préférable, qu'un objet contrôle son propre thread. L'objet est alors autonome. C'est la bonne solution, la plus fréquemment utilisée. class Animation implements Runnable { Thread myThread; // par exemple dans le contructeur Animation (String name) { myThread = new Thread(this); myThread.start(); } ... public void run() {...} Création Thread myThread start() Execution

Création et démarrage - 3 On peut rencontrer cependant la solution suivante : hériter de la classe Thread qui implémente Runnable. redéfinir la méthode run(). class Thread implements Runnable ..... } Animation fun = new Animation("fun"); fun.start(); class Animation extends Thread{ // ... start(); public void run() {...} } // ou bien class Animation extends Thread{ // ... Animation (String name) { start(); }

Thread : illustration

Une vision d’un thread public class Thread { ... private Runnable target; public Thread(){ target = this; } public void start(){ target.run();

Reprenons : utilisation de la classe Thread « The Thread class implements a standard thread that, by default, does nothing. »  Il faut redéfinir la méthode public void run() qui décrit la tâche de l'objet de type Thread. Un thread démarre avec l'appel de la méthode start() qui lance run(). Pour réutiliser, une première possibilité est d'hériter de Thread. Mais notre application (ou notre montre) hérite déjà ! La seconde possibilité implémenter l'interface Runnable et construire un thread qui pour cible un objet Runnable. Il existe l'interface Runnable qui impose la méthode run(). Un objet Runnable contient ce que le thread doit exécuter.

Hériter de Thread ou non. Hériter de Thread semble simple, mais ... Il est important de concevoir vos classes selon une structure objet cohérente : la méthode run() est souvent relative à la fonctionnalité d'une classe particulière (par exemple la montre, l'animation, ...). run() devrait être implémentée dans cette classe, ... plutôt que dans une classe représentant un thread. Implémenter l'interface Runnable permet : de faire un design objet cohérent. d'hériter d'une autre classe que Thread (JFrame, JLabel, ...); permettre à run() d'accéder aux membres privés de la classe.

Contrôle des threads La vie d'une thread démarre par l'appel de start() qui lance run(). stop() détruit le thread en cours. start() et stop() ne peuvent être appelé qu'une fois ! Au contraire de suspend() et resume(). Pour la plupart des utilisations start() et stop() suffisent, c'est lorsque que l'initialisation du thread est importante, qu'il faut utiliser suspend() et resume() : connexion réseau, ressource chargée importante, ... . Le sommeil : try { Thread.sleep(1000); } catch (InterruptedException e) { }

Implémentation de l'éditeur simple - V2 L'application implémente l'interface Runnable. Rédéfinition de la méthode run(). Ajout d'un attribut de type Thread ciblé sur this. Modification de l'ActionListener StartL. ça marche, mais l'application implémente Runnable : incohérent, C'est la montre qui doit être autonome. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class EdMontre2 extends JFrame implements Runnable { /* aux attributs, ajout d'un thread */ ... private Thread selfThread = null; /* Rédéfinition de run. public void run(){ montre.go(); } /* Modification de StartL */ class StartL implements ActionListener { public void actionPerformed(ActionEvent e) { if(selfThread == null) { selfThread= new Thread(EdMontre2.this); selfThread.start(); /* Le reste est inchangé : le main, le contructueur, ... */

Modification de la classe MontreG On crée une nouvelle classe qui hérite de JLabel et qui est Runnable. Redéfinition de la méthode run(). Le constructeur est inchangé. La méthode go() devient inappropriée, elle est supprimée. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class MontreGR extends JLabel implements Runnable{ /* Le constructeur est le même, par contre la méthode go() est supprimée. */ public void run(){ while (true) { try { Thread.sleep(100); } catch(InterruptedException e) { System.err.println("Interrupted"); } this.setText(new java.util.Date(). toString());

Implémentation de l'éditeur simple - V3 L'attribut montre est de type MontreGR. L'attribut de type Thread est conservé. Il aura pour cible l'attribut montre . L'application n'implémente plus l'interface Runnable. Plus de méthode run() dans l’application. Rédéfinition de la méthode run() dans la montre. Modification de l'ActionListener StartL. Peut mieux faire ... . import java.awt.*; import java.awt.event.*; import javax.swing.*; public class EdMontre3 extends JFrame { /* aux attributs, ajout d'un thread */ ... private Thread clockThread = null; /* Modification de StartL */ class StartL implements ActionListener { public void actionPerformed(ActionEvent e) { if(clockThread == null) { clockThread = new Thread(montre); clockThread.start(); } /* Le reste est inchangé : le main, le contructueur, ... */

un thread daemon Propose un service général en tâche de fond. Un programme Java s'arrète une fois que tous les threads sont terminés. tous sauf les daemon. Transformer un thread en daemon : setDaemon(true); isDaemon(); Pour la montre, mieux qu'un thread, un daemon.

Hériter de Thread du livre de Bruce Eckel public class SimpleThread extends Thread { private int countDown = 5; private static int threadCount = 0; private int threadNumber = ++threadCount; public SimpleThread() { System.out.println("Making " + threadNumber); } public void run() { // la méthode à redéfinir : la tâche du thread. while(true) { System.out.println("Thread " + threadNumber + "(" + countDown + ")"); if(--countDown == 0) return; public static void main(String[] args) { for(int i = 0; i < 5; i++) new SimpleThread().start();// l'appel de start lance le thread (run) System.out.println("All Threads Started"); du livre de Bruce Eckel

execution de simpleThread Making 1 Making 2 Making 3 Making 4 Making 5 Thread 1(5) Thread 1(4) Thread 1(3) Thread 1(2) Thread 2(5) Thread 2(4) Thread 2(3) Thread 2(2) Thread 2(1) Thread 1(1) All Threads Started Thread 3(5) Thread 4(5) Thread 4(4) Thread 4(3) Thread 4(2) Thread 4(1) Thread 5(5) Thread 5(4) Thread 5(3) Thread 5(2) Thread 5(1) Thread 3(4) Thread 3(3) Thread 3(2) Thread 3(1)

Exemple de partage de ressources public class PrimeThread extends Thread int valeur = 0; // valeur est une variable d’instance public void run() { while (true) { System.out.println("thread 18 fait son boulot : "); doJob(18); } public void doJob(int newValeur) { int oldValeur = valeur; valeur = newValeur; System.out.println(" valeur = "+valeur); if (valeur != newValeur) { System.out.println(" ZUT Val="+valeur+" et arg="+newValeur); valeur = oldValeur; Attention aux deux appels de fonctions doJob() est appelé par run() et…

Lancement public class TestThread { public static void main(String[] ags) { PrimeThread thread1 = new PrimeThread (); thread1.start(); while (true) { System.out.println("L'annee utilisee est : "); thread1.doJob(1789); } Attention aux deux appels de fonctions doJob() est aussi appelé par main()

Résultat L'annee utilisee est : Valeur = 1789 ZUT Val=1789 et Arg=18 thread 18 fait son boulot : Valeur = 18 Valeur = 1789 L'annee utilisee est : L'annee utilisee est : Valeur = 1789 ZUT Val=1789 et Arg=18

Exemple : Feuille de calcul, tableau dynamique public class SpreadSheet { int cellA1, cellA2, cellA3; public int sumRow() { return cellA1 + cellA2 + cellA3; } public void setRow( int a1, int a2, int a3 ) { cellA1 = a1; cellA2 = a2; cellA3 = a3; ... Que se passe-t-il si deux threads manipulent un même objet de type SpreadSheet et appellent au même moment sumRow()et setRow() ?

Synchronisation Prévenir les collisions au niveau de l'objet et de sa mémoire. Déclarer une méthode synchonized : un seul thread à la fois peut appeler une méthode synchronized pour un objet donné. Principe d'encapsulation + synchronized : l'accès aux membres privés se fait via des méthodes synchronized.

Verrou (lock) Chaque objet possède un « «monitor » en tant qu'Object. Pour garantir qu’un bout de code n’est exécuté par un seul thread à la fois : synchronized(unObjet){... un seul à la fois ...} Lors de l'appel d'une méthode synchronized : l'objet est-il accessible (non-vérouillé) ? si oui, la méthode est exécutée et l'objet verrouillé; si non, la méthode doit attendre la levée du verrou (que la méthode qui « a le verrou » ai terminé). Pour un objet, 1 seul verrou est partagé par toutes les méthodes synchronized.

Exemple : spreadSheet (suite) public class SpreadSheet { int cellA1, cellA2, cellA3; public synchronized int sumRow() { return cellA1 + cellA2 + cellA3; } public synchronized void setRow( int a1, int a2, int a3 ) { cellA1 = a1; cellA2 = a2; cellA3 = a3; ... Que se passe-t-il si une seule des méthodes est déclarée synchronized ?

Critical section Pour partiellement synchroniser une partie d'une méthode : du code « critique »  public void run() { while (true) { synchronized(this) { t1.setText(Integer.toString(count1++)); t2.setText(Integer.toString(count2++)); } try { sleep(500); } catch(InterruptedException e) { System.err.println("Interrupted");

Synchronisation généralisée Synchroniser ce que l'on veut, sur ce que l'on veut. synchronized(syncObject){ /* Ce code ne peut être exécuter que par un seul thread à la fois */ ... } Ainsi les 2 morceaux de codes suivants sont équivalents. void myMethod () { synchronized (this) { ... } synchronized void myMethod () { ... }

wait() et notify() Dans une méthode synchronized Le verrou est bloqué à l’entrée puis débloqué à la sortie Si au milieu de la méthode un thread se rend compte qu’il ne peux pas remplir ses objectifs car un autre Thread bloqué doit avancer avant ? INTERBLOQUAGE = cauchemar. Mieux vaut passer la main si on ne peut plus avancer. Exemple classique du producteur/consommateur Le producteur fonctionne en flux tendu avec un stock très limité. Le consommateur consomme le produit à son rythme (il est parfois un peu lent). Le producteur doit attendre le consommateur pour produire.

Producteur / Consommateur Le producteur : contient un Vector de message le thread Producteur ajoute un message au vecteur par seconde Mais le vecteur a une taille maximale Dans ce cas la méthode putMessage «  tourne en rond». Le consommateur : consomme un message toutes les 2 secondes avec la méthode getMessage du producteur. Synchronisation : les deux méthodes getMessage et putMessage accède au même vecteur ! Il faut donc les synchroniser.

Le producteur import java.util.Vector; public class Producer extends Thread { static final int MAXQUEUE = 5; private Vector messages = new Vector(); public void run() { try { while ( true ) { putMessage(); sleep( 1000 ); } catch( InterruptedException e ) { } private synchronized void putMessage() throws InterruptedException { while (messages.size() == MAXQUEUE){ System.out.println("Waiting”); messages.addElement(new java.util.Date().toString()); // Called by Consumer public synchronized String getMessage() throws InterruptedException { while ( messages.size() == 0 ) try { sleep( 1000 ); } catch(InterruptedException e){} String message = (String) messages.firstElement(); messages.removeElement(message); return message;

Le consommateur import java.util.Vector; public class Consumer extends Thread { Producer producer; // quel est son producteur. Consumer(Producer p) { producer = p; } public void run() { try { while ( true ) { String message = producer.getMessage(); System.out.println("Got message: " + message); sleep( 2000 ); // il est un peu lent. catch( InterruptedException e ) { } public static void main(String args[]) { Producer producer = new Producer(); producer.start(); new Consumer( producer ).start();

Interblocage

Le producteur - 2 import java.util.Vector; public class Producer extends Thread { static final int MAXQUEUE = 5; private Vector messages = new Vector(); public void run() { try { while ( true ) { putMessage(); sleep( 1000 ); } catch( InterruptedException e ) { } private synchronized void putMessage() throws InterruptedException { while (messages.size() == MAXQUEUE){ wait(); // Attendons System.out.println("Waiting”); messages.addElement(new java.util.Date().toString()); notify(); // Reprenons // Called by Consumer public synchronized String getMessage() throws InterruptedException { while ( messages.size() == 0 ) wait(); // Attendons String message = (String) messages.firstElement(); messages.removeElement(message); notify(); // Reprenons return message; }

Le résultat avec wait et notify Got message: Tue Nov 08 23:46:48 CET 2005 Got message: Tue Nov 08 23:46:49 CET 2005 Got message: Tue Nov 08 23:46:50 CET 2005 Got message: Tue Nov 08 23:46:51 CET 2005 Waiting Got message: Tue Nov 08 23:46:52 CET 2005 Got message: Tue Nov 08 23:46:53 CET 2005 ....

wait en détail (I. Charon) wait est héritée de la classe Object. Cette instruction s’utilise dans un code synchronisé. Le thread en cours d'exécution attend. La méthode doit être invoquée sur l'instance verrouillée. Typiquement, on pourra écrire : synchronized(UnObjet) { ... while (condition) unObjet.wait(); } Le thread en cours d'exécution est bloqué par unObjet. L'instruction unObjet.wait() signifie que unObjet bloque le thread en cours d'exécution. Ce n'est pas unObjet qui attend. Pendant que la thread attend, le verrou sur unObjet est relâché.

notify en détail (I. Charon) Pour pouvoir débloquer un thread qui attend, bloqué par unObjet : synchronized(refereMemeObjetQuUnObjet) { ... refereMemeObjetQuUnObjet.notify(); } Si plusieurs threads sont dans l’attente imposée par unObjet, l'instruction notify() débloque celle qui attend depuis le plus longtemps. Sinon notifyAll(). Signalons qu'il existe aussi wait(long temps) qui termine l'attente après temps millisecondes, si cela n'est pas fait auparavant.

Exemple du pont Supposons un pont entre la France et l’Angleterre. Le pont peut être utilisé par un nombre maximum de nmax voitures. Comment gérer le trafic ? Sachant qu’une voiture ne fait que : demander l’autorisation de passer quand le feu est vert, elle passe. Le pont est une ressource partagée par les voitures : une méthode autorisation() une méthode traversee() Toutes les voitures ne peuvent pas accéder au pont en même temps. Regardons le main, la voiture. 

Planification des threads Lorsqu'un thread est lancé, il garde la main jusqu'à ce qu'il atteigne un des états suivants : Sleeps : appel de Thread.sleep() ou wait(). Waits for lock : une méthode synchronized est appellée, mais le thread n'a pas le verrou. Blocks on I/O : lecture de fichier, attente reseau. Explicit yield control : appel de yield(). Terminates : la méthode run() du thread est terminé ou appel de stop(). Qui prend la main ensuite ?

Gestion des priorités Java propose quelques garanties sur comment les threads sont planifiées (scheduled). Chaque thread possède une priorité. Si 2 Threads se battent pour obtenir la main … Si un Thread de plus haute priorité veut la main il l’obtient Si 2 Threads de même priorité se battent : Time slicing Un thread hérite de la priorité de son créateur. La priorité peut être modifiée : int myPriority = Thread.MIN_PRIORITY; thread1.setPriority(myPriority+1); La classe Thread posède les constantes Thread.MIN_PRIORITY (resp. MAX et NORM).

Plannification et yield Un thread peut donner de son temps volontairement par l'appel de yield(). Pour faire alterner des threads, c'est la bonne solution. La méthode sleep() doit servir que lorsque l'on souhaite imposer un temps donner de sommeil. S'il s'agit de passer la main : yield().

Reprenons l'exemple de Bruce public class SimpleThread extends Thread { private int countDown = 5; private static int threadCount = 0; private int threadNumber = ++threadCount; public SimpleThread() { System.out.println("Making " + threadNumber); } public void run() { // la méthode à redéfinir : la tâche du thread. while(true) { System.out.println("Thread " + threadNumber + "(" + countDown + ")"); if(--countDown == 0) return; public static void main(String[] args) { for(int i = 0; i < 5; i++) new SimpleThread().start();// l'appel de start lance le thread (run) System.out.println("All Threads Started"); du livre de Bruce Eckel

le résultat sur une autre machine (autre OS). Making 1 Making 2 Making 3 Making 4 Thread 1(5) Thread 1(4) Thread 1(3) Thread 1(2) Thread 1(1) Thread 2(5) Thread 2(4) Thread 2(3) Thread 2(2) Thread 2(1) Thread 3(5) Thread 3(4) Thread 3(3) Thread 3(2) Thread 3(1) Making 5 All Threads Started Thread 4(5) Thread 4(4) Thread 4(3) Thread 4(2) Thread 4(1) Thread 5(5) Thread 5(4) Thread 5(3) Thread 5(2) Thread 5(1)

Avec yield() du livre de Bruce Eckel public class SimpleThread extends Thread { private int countDown = 5; private static int threadCount = 0; private int threadNumber = ++threadCount; public SimpleThread() { System.out.println("Making " + threadNumber); } public void run() { while(true) { System.out.println("Thread " + threadNumber + "(" + countDown + ")"); if(--countDown == 0) return; yield(); ........ du livre de Bruce Eckel

le résultat avec yield() Making 1 Making 2 Making 3 Making 4 Making 5 Thread 1(5) Thread 2(5) Thread 3(5) All Threads Started Thread 4(5) Thread 1(4) Thread 2(4) Thread 3(4) Thread 5(5) Thread 4(4) Thread 1(3) Thread 2(3) Thread 3(3) Thread 5(4) Thread 4(3) Thread 1(2) Thread 2(2) Thread 3(2) Thread 5(3) Thread 4(2) Thread 1(1) Thread 2(1) Thread 3(1) Thread 5(2) Thread 4(1) Thread 5(1)

Je veux terminer mon travail ! Joining a thread One thread may call join( ) on another thread to wait for the second thread to complete before proceeding. If a thread calls t.join( ) on another thread t, then the calling thread is suspended until the target thread t finishes (when t.isAlive( ) is false). You may also call join( ) with a timeout argument so that if the target thread doesn’t finish in that period of time, the call to join( ) returns anyway.

Timer : Simple et Utile Pragmatiquement Un Thread pour repousser une action dans le temps Dans 3 secondes, si l’utilisateur n’a pas bougé sa souris, afficher un popup disans « Ce bouton sert à quitter le document » Un Thread pour répéter une action régulièrement Tous les 0.5 secondes, redessine la barre de progression. Pour ces cas simple, pas besoin de faire des Threads compliqués : Utiliser un Timer ! Tutorial Java ->Essential ->Threads ->Timer http://java.sun.com/docs/books/tutorial/essential/threads/timer.html Déclencher une action tout en continuant Déclencher une action après n millisecondes Déclencher des actions toutes les p millisecondes

Exemple Tutorial Java ->Essential ->Threads ->Timer http://java.sun.com/docs/books/tutorial/essential/threads/timer.html Déclencher une action tout en continuant Déclencher une action après n millisecondes Déclencher des actions toutes les p millisecondes