IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Concurrence et multi-thread Java Discussion :

Problème Thread wait / Notify


Sujet :

Concurrence et multi-thread Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 139
    Points : 53
    Points
    53
    Par défaut Problème Thread wait / Notify
    Bonjour à tous,

    j'ai un petit problème de wait sur un Thread qui même après un appel de la méthode notify ne se débloque pas...

    voici le code de la casse Thread:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    public class USBThread extends Thread{
    ...
     
    	public static USBThread getInstance(){
    	    if( instance == null ) { instance = new USBThread(); }
    	    return instance;
    	}
     
    	public void run(){
                    .......
    		while(fin != 1){
    			synchronized(this){
    				try{
    					this.wait();
    					log.debug("Traitement du message");
                                            process();
     
    				}catch(Exception e){}
    			}
    		}
    et voici la classe qui utilise ce thread.
    En fait je crée un objkect USBThread, je récupère sa référence, je modifie un de ses objet et je notifie le thread pour qu'il puisse processer mon objet envoyé:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
                            USBThread usb = USBThread.getInstance();
     
    			synchronized(usb){
    				usb.sendCommand(commande);
    				usb.notify();
    			}
    lorsque cette classe appelle la méthode notify de mon threadUSB, je n'ai pas d'affichage de la chaine "Traitement du message", ni de lancement de la méthode process().

    Quelqu'un pourrait m'éclairer à ce sujet ? je bloque....

    Merci !
    Tiamat.

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Question bête mais : le thread est-il bien lancé ?
    Sinon avec Java 5 tu peux utiliser une BlockingQueue pour cela


    a++

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 139
    Points : 53
    Points
    53
    Par défaut
    Salut adiGuba,

    oui je te confirm que le Thread est bien lancé car j'effectue une initialisation dans le Thread avant de pouvoir processer mes commandes (ouverture du port USB).

    Je vais regarder les Blocking Queue, mais étant donné que mon besoin reste assez basique, je sais que je n'aurais toujours qu'un seul thread USB, le seul truc c'est que c'est lui qui est garant de la connection USB et toute demande de traitement de commande doit passer par lui...

    pour moi la boucle infinie en attente de notify() semblait une solution parfaite pour mettre le Thread en attente de processing de commande...

  4. #4
    Membre à l'essai
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Salut,


    Question bête mais : le thread est-il bien lancé ?


    a++
    Il n'y a aucun appel de la méthode start() pour lancer le thread.

  5. #5
    Membre à l'essai
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Points : 18
    Points
    18
    Par défaut
    Salut:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public static USBThread getInstance(){
         if( instance == null || !instance.isAlive())  { 
              instance = new USBThread();
              instance.start();
         }
         return instance;
    }

  6. #6
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tiamat Voir le message
    pour moi la boucle infinie en attente de notify() semblait une solution parfaite pour mettre le Thread en attente de processing de commande...
    Comme tu ne peux pas déterminer l'ordre d'exécution des threads, il est possible que le notify() soit exécuté AVANT le wait() : du coup ton thread s'endort et ne se réveille plus....


    Il faudrait rajouter un double-check qui vérifie s'il y a des données avant le wait()...



    Mais les BlockingQueue sont justement là pour résoudre ce problème :


    a++

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 139
    Points : 53
    Points
    53
    Par défaut
    j'ai un peu regardé les BlockingQueue mais au plus j'y réfléchis au plus je me dit que l'utilisation des Thread "standards" est largement suffisante pour mon besoin (en tout cas pour le moment)...

    donc je tente d'investiguer un peu plus sur mon problème...ça doit marcher !

    du fait ta remarque sur l'ordre entre le notify et le wait est obligatoirement bon dans mon soft, mon Thread se met en wait() au démarrage de mon programme et je suis persuadé que que le notify arrive après.

    donc si j'énumère:
    - je suis sur que c'est le même Thread à qui j'envois un notify (en affichant la ref du Thread j'ai vu que c'est le même instancié au début et celui à qui j'envois un notify)
    - je n'ai pas d'exception, j'ai juste mon thread qui n'est jamais réveillé

    Avez vous une idée ? si vous voulez je peux vous faire passer un peu plus de code pour expliquer un peu mieux !

    Merci,
    Tiamat.

  8. #8
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    met un log avant le wait(), pour être sur.
    met un log avant le notify(), pour etre sur aussi.
    a mon avis, soit le thread est pas lancé, soit le notify arrive trop tot par rapport au wait, soit tu fait pas le notify, soit encore t'as plusieurs trucs qui font un wait sur le meme objet

    et en multi threading, on ne peut pas être persuadé qu'un notify arrive bien après un wait, il faut en etre sur, et ton code n'en donne aucune garantie

  9. #9
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tiamat Voir le message
    du fait ta remarque sur l'ordre entre le notify et le wait est obligatoirement bon dans mon soft, mon Thread se met en wait() au démarrage de mon programme et je suis persuadé que que le notify arrive après.
    Rien ne garantie cela dans le code que tu as donné...

    D'ailleurs en reproduisant un code proche du tiens j'obtiens le même type de problème : le notify() est appelée avant le wait() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    	Thread thread = new Thread() {
    		@Override
    		public void run() {
    			synchronized(this) {
    				try {
    					System.out.println("Wait");
    					this.wait();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	};
    	thread.start();
     
    	synchronized(thread) {
    		System.out.println("Notify");
    		thread.notify();
    	}
    Tu as deux threads différents, et l'ordre d'exécution peut entre les deux threads peut fortement varier selon plusieurs conditions (l'OS, la charge système, etc.). Il est impossible de garantir l'ordre d'exécution exact...



    Donc si tu veux faire cela avec des wait/notify, il faut que tu utilises une variables externes (un booléen ou simplement la taille d'une liste) afin d'éviter d'endormir ton thread s'il y a déjà eu un notify (par exemple si tu as déjà reçu une commande.

    En gros ton thread devrait ressembler à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    class MyThread extends Thread {
     
    	// Les accès à la liste doivent être synchronisé
    	private final List<String> list = new LinkedList<String>();
     
    	/**
             * La méthode sendCommand() doit être appellé depuis un autre thread
             * pour "passer" un objet au thread...
             */
    	public void sendCommand(String command) {
    		synchronized(this) {
    			// On a le verrou, on peut modifier la liste :
    			this.list.add(command);
    			// Et on signale cet ajout au thread :
    			this.notify();
    		}
    	}
     
    	/**
             * La méthode getCommand() doit être appelée par le thread pour récupérer
             * le premier élément reçu via sendCommand().
             * S'il n'y a aucun élément la méthode bloquera jusqu'à en recevoir un...
             */	
    	protected String getCommand() {
    		synchronized(this) {
    			// On a le verrou, on peut vérifier l'état de la liste :
    			while (list.isEmpty()) {
    				// On endort le thread tant que la liste est vide :
    				try {
    					this.wait();
    				} catch (InterruptedException e) {
    					throw new RuntimeException(e);
    				}
    			}
    			// Et on retourne le premier élément :
    			return list.remove(0);
    		}
    	}
    }

    Et là si le notify est appelé AVANT le wait, tu n'endors pas le thread et tu traite de suite les données :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class Main {
     
    	public static void main(String[] args) {
     
    		MyThread thread = new MyThread() {
    			@Override
    			public void run() {
    				synchronized(this) {
    					System.out.println("getCommand()");
    					String command = getCommand();
    					System.out.println("command="+command);
    				}
    			}
    		};
    		thread.start();
     
     
    		System.out.println("setCommand()");
    		thread.sendCommand("hello");
     
    	}
     
    }

    Les BlockingQueue gèrent toute cette synchronisation pour toi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    class MyThread extends Thread {
     
    	// Les BlockingQueue gère toute la partie synchronisation,
    	// et peuvent donc être utilisé directement depuis n'importe quel thread :
    	private final BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
     
    	/**
             * La méthode sendCommand() doit être appelée depuis un autre thread
             * pour "passer" un objet au thread...
             */
    	public void sendCommand(String command) {
    		this.queue.offer(command);
    	}
     
    	/**
             * La méthode getCommand() doit être appelée par le thread pour récupérer
             * le premier élément reçu via sendCommand().
             * S'il n'y a aucun élément la méthode bloquera jusqu'à en recevoir un...
             */
    	protected String getCommand() {
    		try {
    			return this.queue.take();
    		} catch (InterruptedException e) {
    			throw new RuntimeException(e);
    		}
    	}
    }

    a++

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 139
    Points : 53
    Points
    53
    Par défaut
    Merci pour vos remarques,
    je tente encore un peu de m'acharner dessus et si je vois que c'est trop galère effectivement je me pencherais un peu plus sur les BlockingQueues....

    Bref, j'ai rajouté quelques logs supplémentaires, voici le ThreadUSB:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    	//Merci Mister Joker ! ;-)
            public static USBThread getInstance(){
    	    if( instance == null || !instance.isAlive() ) {
    	    	instance = new USBThread(); 
    	    	instance.start();
    	    }
    	    return instance;
    	}
     
    	public void run(){
    		Random rand = new Random();
    		ref = rand.nextInt(9999);
    		instance = this;
    		cmd = null;
    		log.debug("Demarrage Thread USB "+ref);
    		//demarrage du thread d'ecoute USB
    		log.debug("Thread USB initialise.");
    		//com.start();		
    		while(fin != 1){
    			synchronized(this){
    				try{
    					log.debug("Thread USB en Wait");
    					this.wait();
    					log.debug("Thread USB sorti du wait, traitement du message");
    					process();				
    					cmd = null;				
    				}catch(Exception e){
    					if (log.isDebugEnabled()) {
    						log.debug("Erreur de Thread USB.... :("+e.toString());
    					} else {
    						log.error(e, e);
    					}
    				}
    			}
    		}
    	}
    voici la Servlet qui l'appelle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    ...
    USBThread usb = USBThread.getInstance();
    ....
    			synchronized(usb){
    				log.debug("Envoi de Notify au Thread USB ");
    				usb.sendCommand(commande,step,vitesse);
    				usb.notify();
    			}
    pour ce qui est des logs, les voicis:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    12:42:04,674 WARN  [com.emi.module.Main]:25 - Demarrage du module [EMI2]
    12:42:04,674 WARN  [com.emi.module.Main]:26 - Module en mode ONLINE
    12:42:04,705 DEBUG [com.emi.Config]:64 - Modifie Module Mode: OFFLINE ->ONLINE
    12:42:04,705 DEBUG [com.emi.module.USBCard]:69 - Demarrage Thread USB 841
    12:42:04,705 DEBUG [com.emi.module.USBCard]:80 - Thread USB initialise.
    12:42:04,705 DEBUG [com.emi.module.USBCard]:85 - Thread USB en Wait
    12:42:40,111 DEBUG [com.emi.module.Servlets]:90 - Commande:go
    12:42:40,111 DEBUG [com.emi.module.Servlets]:106 - On envoit la commande au Thread USB
    12:42:40,111 DEBUG [com.emi.module.Servlets]:111 - Envoi de Notify au Thread USB
    12:42:40,111 INFO  [com.emi.module.USBCard]:31 - commande recue a envoyer, je suis le Thread : 841
    selon les logs, on voit bien que le ThreadUSB instance 841 est en wait avant le notify, et je suis bien sur d'envoyer le notify au bon Thread étant donné que la commande est bien reçue par le ThreadUSB ayant la bonne ref 841.

    qu'en pensez vous ?

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 139
    Points : 53
    Points
    53
    Par défaut
    En parallèle j'ai essayé les BlockingQueues que tu me proposes adiGuba, mais j'ai le même résultat...

    voici l'extrait du code modifié:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    ThreadUSB:
    	public void sendCommand(String command){
    		log.info("Thread USB sendCommand recu, je suis le Thread : "+ref);
    		this.queue.offer(command);
     
    	}
     
    	protected String getCommand() {
    		try {
    			return this.queue.take();
    		} catch (InterruptedException e) {
    			throw new RuntimeException(e);
    		}
    	}
    ....
    		log.debug("Thread USB initialise.");
    		//com.start();		
    		while(fin != 1){
    			synchronized(this){
    				try{
    					log.debug("Thread USB en Wait");
    					//this.wait();
    					getCommand();
    					log.debug("Thread USB sorti du wait, traitement du message");
    					process();				
    					cmd = null;				
    				}catch(Exception e){
    					if (log.isDebugEnabled()) {
    						log.debug("Erreur de Thread USB.... :("+e.toString());
    					} else {
    						log.error(e, e);
    					}
    				}
    			}
    		}
    et voici mon appellant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    			log.debug("la Servlet envoit la commande au Thread USB");
    			log.debug("Envoi de Notify au Thread USB ");
    			usb.sendCommand(commande,step,vitesse);

    voici le résultat des Logs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    13:15:51,788 WARN  [com.emi.module.Main]:25 - Demarrage du module [EMI2]
    13:15:51,788 WARN  [com.emi.module.Main]:26 - Module en mode ONLINE
    13:15:51,803 DEBUG [com.emi.Config]:64 - Modifie Module Mode: OFFLINE ->ONLINE
    13:15:51,803 DEBUG [com.emi.module.USBCard]:83 - Demarrage Thread USB 7781
    13:15:51,803 DEBUG [com.emi.module.USBCard]:94 - Thread USB initialise.
    13:15:51,803 DEBUG [com.emi.module.USBCard]:99 - Thread USB en Wait
    13:16:06,207 DEBUG [com.emi.module.Servlets]:105 - la Servlet envoit la commande au Thread USB
    13:16:06,207 DEBUG [com.emi.module.Servlets]:107 - Envoi de Notify au Thread USB
    13:16:06,207 INFO  [com.emi.module.USBCard]:32 - Thread USB sendCommand recu, je suis le Thread : 7781
    Le résultat est donc le même en utilisant les BlockingQueue, j'ai également tenté de lever le bloc synchronized dans ma méthode run() de mon Thread mais le résultat est le même...

  12. #12
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    1) es-tu sur d'avoir bien compilé après avoir retiré le wait()?
    2) pourquoi ne stocke tu pas le retour de getCommand() quelque part
    3) j'ai testé ton code, avec quelques modif (retiré log4j), il fonctionne parfaitement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    package pack1;
     
    import java.util.Random;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
     
    public class USBThread extends Thread {
     
        BlockingQueue<String> queue = new ArrayBlockingQueue<String>(50);
        private int ref;
        private static USBThread instance;
        private int fin;
        private String cmd;
     
        public void sendCommand(String command){
            System.out.println("Thread USB sendCommand "+command+" recu , je suis le Thread : "+ref);
            this.queue.offer(command);
     
        }
     
        protected String getCommand() {
            try {
                return this.queue.take();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
     
        //Merci Mister Joker ! ;-)
        public static USBThread getInstance(){
            if( instance == null || !instance.isAlive() ) {
                instance = new USBThread();
                instance.start();
            }
            return instance;
        }
     
        public void run(){
            Random rand = new Random();
            ref = rand.nextInt(9999);
            instance = this;
            cmd = null;
            System.out.println("Demarrage Thread USB "+ref);
            //demarrage du thread d'ecoute USB
            System.out.println("Thread USB initialise.");
            //com.start();
            while(fin != 1){
                synchronized(this){
                    try{
                        System.out.println("Thread USB en Wait");
                        //this.wait();
                        cmd = getCommand();
                        System.out.println("Thread USB sorti du wait, traitement du message");
                        process();
                        cmd = null;
                    }catch(Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
     
        private void process() {
            System.out.println("processing "+cmd);
            try {
                Thread.sleep(50); //simule du temps passé à traiter l'opération
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
     
        public static void main(String[] argv) throws InterruptedException{
            Random r = new Random();
            for (int i=0;i<10;i++){
                Thread.sleep(r.nextInt(30));
                getInstance().sendCommand("command "+i);
            }
        }
    }
    résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    Demarrage Thread USB 1624
    Thread USB initialise.
    Thread USB en Wait
    Thread USB sendCommand command 0 recu , je suis le Thread : 1624
    Thread USB sorti du wait, traitement du message
    processing command 0
    Thread USB sendCommand command 1 recu , je suis le Thread : 1624
    Thread USB sendCommand command 2 recu , je suis le Thread : 1624
    Thread USB en Wait
    Thread USB sorti du wait, traitement du message
    processing command 1
    Thread USB sendCommand command 3 recu , je suis le Thread : 1624
    Thread USB sendCommand command 4 recu , je suis le Thread : 1624
    Thread USB sendCommand command 5 recu , je suis le Thread : 1624
    Thread USB en Wait
    Thread USB sorti du wait, traitement du message
    processing command 2
    Thread USB sendCommand command 6 recu , je suis le Thread : 1624
    Thread USB sendCommand command 7 recu , je suis le Thread : 1624
    Thread USB sendCommand command 8 recu , je suis le Thread : 1624
    Thread USB sendCommand command 9 recu , je suis le Thread : 1624
    Thread USB en Wait
    Thread USB sorti du wait, traitement du message
    processing command 3
    Thread USB en Wait
    Thread USB sorti du wait, traitement du message
    processing command 4
    Thread USB en Wait
    Thread USB sorti du wait, traitement du message
    processing command 5
    Thread USB en Wait
    Thread USB sorti du wait, traitement du message
    processing command 6
    Thread USB en Wait
    Thread USB sorti du wait, traitement du message
    processing command 7
    Thread USB en Wait
    Thread USB sorti du wait, traitement du message
    processing command 8
    Thread USB en Wait
    Thread USB sorti du wait, traitement du message
    processing command 9
    Thread USB en Wait

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 139
    Points : 53
    Points
    53
    Par défaut
    1) es-tu sur d'avoir bien compilé après avoir retiré le wait()?
    oui j'ai effectivement bien compilé, j'ai bien fait un clean plusieurs fois.
    2) pourquoi ne stocke tu pas le retour de getCommand() quelque part
    juste parce que je ne procédais pas comme ça pour passer mes arguments au Thread, je pourrais effectivement utiliser cette méthode mais je ne pense pas que cela puisse bloquer mon thread
    3) j'ai testé ton code, avec quelques modif (retiré log4j), il fonctionne parfaitement:
    J'ai repris ton code d'exemple pour isoler cette fonction et chez moi aussi il tourne...donc je ne comprend vraiment pas pourquoi mon thread ne se réveille pas...
    je bloque là...

  14. #14
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    ben donne nous tout le code de ta classe Thread et de l'appel à celle-ci, parce que là, nous, on a que des bouts qui a priori fonctionnent (cf mon code)

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 139
    Points : 53
    Points
    53
    Par défaut
    le voici:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
     
    package com.emi.module.USBCard;
     
    import java.util.*;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ConcurrentLinkedQueue;
    import java.util.concurrent.LinkedBlockingQueue;
     
    import com.emi.module.Entity.*;
     
    import org.apache.log4j.Logger;
    import com.emi.module.Entity.XMLOperativeCommand;
     
    public class USBThread extends Thread{
     
    	private static final Logger log = Logger.getLogger("com.emi.module.USBCard");
    	private static USBThread instance;
    	private static int ref;
    	private int fin = 0;
    	private final BlockingQueue<Action> queue = new LinkedBlockingQueue<Action>();
    	private Action action;
    	private ComUSB com;
    	private XMLOperativeCommand cmd;
     
    	public void sendCommand(String command, String step, String vitesse){
    		log.info("Thread USB sendCommand recu, je suis le Thread : "+ref);
    		action.setName(command);
    		action.setStep(step);
    		action.setSpeed(vitesse);
    		this.queue.offer(action);
     
    	}
     
    	protected Action getCommand() {
    		try {
    			log.debug("Thread USB getCommand: en attente de take(), ref:"+ref);
    			return this.queue.take();
    		} catch (InterruptedException e) {
    			throw new RuntimeException(e);
    		}
    	}
     
     
    	public static USBThread getInstance(){
    	    if( instance == null || !instance.isAlive() ) {
    	    	log.debug("GetInstance Nouvelle reference creee, ref:"+ref);
    	    	instance = new USBThread(); 
    	    	instance.start();
    	    }
    	    return instance;
    	}
     
    	public String getUSBState(){
    		return "SIMULATED OK";
    	}
     
    	public int getRef() {
    		return ref;
    	}
     
    	public void setRef(int ref) {
    		this.ref = ref;
    	}
     
    	public void fin(){
    		fin = 1;
    	}
     
    	public void run(){
    		Random rand = new Random();
    		ref = rand.nextInt(9999);
    		instance = this;
    		cmd = null;
    		log.debug("Demarrage Thread USB "+ref);
    		//demarrage du thread d'ecoute USB
    		log.debug("Thread USB initialise.");
    		while(fin != 1){
    			//synchronized(this){
    				//try{
    					log.debug("Thread USB en Wait");
    					//this.wait();
    					action = getCommand();
    					log.debug("Thread USB sorti du wait, traitement du message");
    					process();				
    					cmd = null;				
    				/*}catch(Exception e){
    					if (log.isDebugEnabled()) {
    						log.debug("Erreur de Thread USB.... :("+e.toString());
    					} else {
    						log.error(e, e);
    					}
    				}*/
    			//}
    		}
    	}
    Je te remercie de ton aide !

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 139
    Points : 53
    Points
    53
    Par défaut
    pardon j'ai oublié l'appellant....

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
     
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
     
    import org.apache.log4j.Logger;
     
     
    public class EMIModuleServlet extends HttpServlet{
     
    	private static final long serialVersionUID = 1L;
    	private static final Logger log = Logger.getLogger("com.emi.module.Servlets");
    	private ModuleConfiguration config = new ModuleConfiguration();
    	private String resultat = "attente de commande";
    	private String commande="";
    	private final ConcurrentLinkedQueue<Action> queue = new ConcurrentLinkedQueue();
    	private Action action= new Action();
    	private String vitesse=null;
    	private String step=null;
    	public HttpSession session_module;
     
    	public void init() throws ServletException {
     
    	}
     
    	public void destroy() {
    	}
     
    	public void doGet(HttpServletRequest request, HttpServletResponse response)
    	throws ServletException, IOException {
     
    		USBThread usb = USBThread.getInstance();
    		//on recupere le path de la requete
    		String cmd=request.getPathInfo();
    		request.setAttribute("moduleState", config.getMode());
    		request.setAttribute("moduleName", config.getModuleName());
    		request.setAttribute("USBState", usb.getUSBState());
    		session_module = request.getSession(true);
     
    		commande = request.getParameter("commande");
    		step = request.getParameter("step");
    		vitesse = request.getParameter("vitesse");
    		resultat = "Commande:"+commande+" Vitesse:"+vitesse;
    		request.setAttribute("resultat", resultat);
    		//Envoi de la commande au Thread USB.
    		log.debug("la Servlet envoit la commande au Thread USB");
    		//synchronized(usb){
    			log.debug("Envoi de Notify au Thread USB ");
    			usb.sendCommand(commande,step,vitesse);
    			//usb.notify();
    		//}
     
    		getServletContext().getRequestDispatcher("/console.jsp").forward(request, response);
    	}
     
    	public void doPost(HttpServletRequest request, HttpServletResponse response)
    	throws ServletException, IOException {
     
    		doGet(request, response);
     
    	}
     
     
     
    }
    le code n'est pas clean...un peu normal j'ai tenté pas mal de choses en // et je dois nettoyer tout ça plus tard !

  17. #17
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    a priori, ca

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    action.setName(command);
    dans sendCommand, ca va systématiquement lever un NullPointerException puisque ton champ action n'est jamais initialisé.

    du coup en fait tu n'envoie jamais la moindre commande dans ton code.

    La méthode correcte serait:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        public void sendCommand(String command, String step, String vitesse){
            log.info("Thread USB sendCommand recu, je suis le Thread : "+ref);
            Action action = new Action();
                   action.setName(command);
            action.setStep(step);
            action.setSpeed(vitesse);
            this.queue.offer(action);
     
        }
    ce qui, accessoirement, en utilisant une variable de méthode plutot qu'un champ global, t'éviterais aussi d'essayer de stocker toujours la même instance réécrasée de Action dans ta queue (ce qui n'aurait aucun sens)

    Ce qui m'étonne, c'est que tu aurais du le voir ici ton NullPointerException, et il aurait du s'afficher dans ta pages html:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    usb.sendCommand(commande,step,vitesse);

  18. #18
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 139
    Points : 53
    Points
    53
    Par défaut
    Effectivement ça venait de là...
    je te remercie parce que j'avais effectivement oublié l'instanciation de l'objet Action...
    mais par contre je n'avais aucune exception de générée d'où ma difficulté à trouver mon erreur ! en tout cas je te remercie tchize (et adiGuba) pour ton aide.
    à charge de revanche ! ;-)

    ++
    Tiamat.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. communication entre thread (wait notify repaint)
    Par jojo410 dans le forum Interfaces Graphiques en Java
    Réponses: 1
    Dernier message: 18/11/2011, 14h08
  2. Problème de wait and notify
    Par Drife dans le forum Général Java
    Réponses: 5
    Dernier message: 06/10/2011, 15h50
  3. problème avec wait() pour un thread
    Par velvet.cassandra dans le forum Général Java
    Réponses: 4
    Dernier message: 30/06/2010, 09h40
  4. [Thread] wait and notify
    Par storm_2000 dans le forum Concurrence et multi-thread
    Réponses: 0
    Dernier message: 27/10/2009, 22h24
  5. [Thread] Probleme sur wait() / notify()
    Par Jean_pierre dans le forum Concurrence et multi-thread
    Réponses: 4
    Dernier message: 30/11/2008, 09h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo