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

Java Discussion :

Composants threadés avec requête via Pile


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Homme Profil pro
    Inscrit en
    Avril 2012
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Avril 2012
    Messages : 49
    Par défaut Composants threadés avec requête via Pile
    Salut à tous

    Ma question n'est pas compliquée mais seul les plus motivés liront mon problème en entier (merci d'avance ).

    Voici la question :
    Est ce correct de faire comme ça ?

    Mon problème :
    J'ai 2 composants et un "client". Mon client est un thread et fait des requêtes au premier composant "Controleur" qui lui même est un Thread et fait des requêtes au composant "Porte" qui est aussi un Thread.

    J'ai volontairement simplifier le problème. Le cheminement est expliqué en commentaire mais n'hésitez pas à poser des questions

    Ma première class est le Main qui lance le Client :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package testthread;
     
    public class TestThread
    {
        public static void main(String[] args)
        {
            Client lui = new Client();
            lui.start();
        }
    }
    Ensuite vient la class Client :
    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
    package testthread;
     
    import java.util.logging.Level;
    import java.util.logging.Logger;
     
    public class Client extends Thread
    {
        /**
         * Le thread client agit sur le controleur :
         */
        private Controleur c;
     
        public Client()
        {
            //J'instancie le Controleur dans le constructeur de Client :
            c = new Controleur();
        }
     
        @Override
        public void run()
        {
            //Le client run, donc je peux lancer mon controleur :
            c.start();
            System.out.println("Client launched =)");
            int i = 0;
            while(true)
            {
                //Le client s'execute...
                execution();
                //...puis envoie des requetes au controleur avec un entier en paramètre
                //(on pourra penser à faire un protocole en chaine de caractère) :
                System.out.println("Le client fait une requete au controleur et envoie " + i);
                c.requete(i);
                i++;
            }
        }
     
        synchronized private void execution()
        {
            try
            {
                this.sleep(2000);
            }
            catch(InterruptedException ex)
            {
                Logger.getLogger(Porte.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    Le composant Controleur :
    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
    package testthread;
     
    import java.util.EmptyStackException;
    import java.util.Stack;
    import java.util.logging.Level;
    import java.util.logging.Logger;
     
    public class Controleur extends Thread
    {
        /**
         * Sous Thread :
         */
        private Porte porte;
        /**
         * Pile de requetes
         */
        private Stack<Integer> pile;
     
        public Controleur()
        {
            porte = new Porte();
            pile = new Stack<Integer>();
        }
     
        @Override
        public void run()
        {
            System.out.println("Controleur launched =)");
            porte.start();
            while(true)
            {
                if(!pile.empty())
                {
                    //On prend la requete en attente :
                    Integer req;
                    synchronized(pile)
                    {
                        req = pile.pop();
                    }
                    //On execute :
                    execution();
                    System.out.println("Le controleur pop " + req);
                    //On fait une requete sur un autre composant :
                    porte.requete(req);
                }
                else
                {
                    try
                    {
                        //Si la pile de requete est vide, on fait dormir le thread :
                        synchronized(this)
                        {
                            System.out.println("--------------------- Le Controleur wait !");
                            this.wait();
                        }
                    }
                    catch(InterruptedException ex)
                    {
                        Logger.getLogger(Controleur.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
     
        synchronized public void requete(int requete)
        {
            //On stoque la requete :
            pile.push(requete);
            System.out.println("Le controleur push " + requete);
            //On reveille le thread pour qu'il traite la requete dans le run :
            System.out.println("--------------------- Le Controleur est notify !");
            this.notify();
        }
     
        /**
         * Fonction permettant d'executer durant 200 ms
         */
        private void execution()
        {
            try
            {
                this.sleep(800);
            }
            catch(InterruptedException ex)
            {
                Logger.getLogger(Porte.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    Le composant Porte :
    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
    package testthread;
     
    import java.util.EmptyStackException;
    import java.util.Stack;
    import java.util.logging.Level;
    import java.util.logging.Logger;
     
    public class Porte extends Thread
    {
        private Stack<Integer> pile;
     
        public Porte()
        {
            pile = new Stack<Integer>();
        }
     
        @Override
        public void run()
        {
            System.out.println("Porte launched =)");
            while(true)
            {
                if(!pile.empty())
                {
                    //On prend la requete en attente :
                    Integer req;
                    synchronized(pile)
                    {
                        req = pile.pop();
                    }
                    //On execute :
                    System.out.println("La porte pop " + req);
                    execution();
                }
                else
                {
                    try
                    {
                        //Si la pile de requete est vide, on fait dormir le thread :
                        synchronized(this)
                        {
                            System.out.println("--------------------- La porte wait !");
                            this.wait();
                        }
                    }
                    catch(InterruptedException ex)
                    {
                        Logger.getLogger(Porte.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
     
        synchronized public void requete(int requete)
        {
            //On stoque la requete :
            pile.push(requete);
            System.out.println("La porte push " + requete);
            //On reveille le thread pour qu'il traite la requete :
            System.out.println("--------------------- La porte est notify !");
            this.notify();
        }
     
        private void execution()
        {
            try
            {
                this.sleep(800);
            }
            catch(InterruptedException ex)
            {
                Logger.getLogger(Porte.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    Voici l’exécution pour mieux comprendre :
    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
    Client launched =)
    Controleur launched =)
    --------------------- Le Controleur wait !
    Porte launched =)
    --------------------- La porte wait !
    Le client fait une requete au controleur et envoie 0
    Le controleur push 0
    --------------------- Le Controleur est notify !
    Le controleur pop 0
    La porte push 0
    --------------------- La porte est notify !
    --------------------- Le Controleur wait !
    La porte pop 0
    --------------------- La porte wait !
    Le client fait une requete au controleur et envoie 1
    Le controleur push 1
    --------------------- Le Controleur est notify !
    Le controleur pop 1
    La porte push 1
    --------------------- La porte est notify !
    --------------------- Le Controleur wait !
    La porte pop 1
    --------------------- La porte wait !
    Le client fait une requete au controleur et envoie 2
    Le controleur push 2
    --------------------- Le Controleur est notify !
    Le controleur pop 2
    La porte push 2
    --------------------- La porte est notify !
    --------------------- Le Controleur wait !
    La porte pop 2
    --------------------- La porte wait !
    Le client fait une requete au controleur et envoie 3
    Le controleur push 3
    --------------------- Le Controleur est notify !
    Le controleur pop 3
    La porte push 3
    --------------------- La porte est notify !

    Ça fonctionne correctement mais je ne suis pas sur que ça soit très conventionnel de faire des "this.wait()" et "this.notify()" quoique... c'est plutôt propre à mon sens !?

    Merci

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2008
    Messages
    1 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 190
    Par défaut
    this.wait et this.notify sont des fonctions parfaitement utilisables et répondant tout à fait à ton besoin.
    Attention tout de même, le wait se réveille après n'importe quel notification reçu sur le thread, et de plus il n'y a pas de pile pour les notifications.
    Ce qui peut être tout à fait le comportement que tu cherches, mais sinon tu peux te tourner vers les sémaphores.

  3. #3
    Expert éminent
    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 : 46
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    il y a quand même pas mal d'erreurs dans ton codes. Par exemple, tu fais un wait en attendant un notify suivant le push. Hors, rien n'empeche d'avoir cette séquence:

    Controlleur: pile est empty? -> oui
    Client: push
    Client: notify
    Controlleur: wait

    Le controlleur pourrait attendre indéfiniment. Tu dois protéger le notify avec un synchronized, et le wait avec le même synchronized. + avant le wait , dans le synchronize, tu dois vérifier que la pile est bien toujours vide.


    Aussi, des classes comme le DeQueue, récentes en Java, sont bien utile pour ce genre de pile et évitent de devoir gérer sois même les notifications

  4. #4
    Membre actif
    Homme Profil pro
    Inscrit en
    Avril 2012
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Avril 2012
    Messages : 49
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    il y a quand même pas mal d'erreurs dans ton codes. Par exemple, tu fais un wait en attendant un notify suivant le push. Hors, rien n'empeche d'avoir cette séquence:

    Controlleur: pile est empty? -> oui
    Client: push
    Client: notify
    Controlleur: wait

    Le controlleur pourrait attendre indéfiniment. Tu dois protéger le notify avec un synchronized, et le wait avec le même synchronized. + avant le wait , dans le synchronize, tu dois vérifier que la pile est bien toujours vide.


    Aussi, des classes comme le DeQueue, récentes en Java, sont bien utile pour ce genre de pile et évitent de devoir gérer sois même les notifications
    Oui très bonne remarque, je n'y avais pas pensé. Du coup l'utilisation d'un BlockingQueue comme le suggère hwoarang résoudrait pas mal de problèmes.

    Merci pour vos réponses.

    J'envoie le code prochainement.

  5. #5
    Membre actif
    Homme Profil pro
    Inscrit en
    Avril 2012
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Avril 2012
    Messages : 49
    Par défaut
    Voilà ce que pourrait donner la BlockingQueue. Je n'est pas testé et c'est sur un autre exemple, désolé...

    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
    package ascenseur;
     
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    import java.util.logging.Level;
    import java.util.logging.Logger;
     
    public class Ascenseur extends Thread
    {
        private int etage;
        private Controleur controleur;
        private BlockingQueue queue;
     
        public Ascenseur(Controleur c)
        {
            this.etage = 0;
            this.controleur = c;
            BlockingQueue queue = new ArrayBlockingQueue(1024);
        }
     
        public int getEtage()
        {
            return etage;
        }
     
        void descendre() throws InterruptedException
        {
            this.etage = 1;
            controleur.requete("aBouge");
        }
     
        void monter() throws InterruptedException
        {
            this.etage = 0;
            controleur.requete("aBouge");
        }
     
        void requete(String requete) throws InterruptedException
        {
            queue.put(requete);
        }
     
        @Override
        public void run()
        {
            while(true)
            {
                try
                {
                    traiter(queue.take());
                }
                catch(InterruptedException ex)
                {
                    Logger.getLogger(Ascenseur.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
     
        private void traiter(Object requete) throws InterruptedException
        {
            requete = (String) requete;
            if(requete.equals("monter"))
                monter();
            else if(requete.equals("descendre"))
                descendre();
        }
    }

  6. #6
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    Citation Envoyé par Soap17 Voir le message
    Ça fonctionne correctement mais je ne suis pas sur que ça soit très conventionnel de faire des "this.wait()" et "this.notify()" quoique... c'est plutôt propre à mon sens !?
    Bah tu cherches à synchroniser et tu utilises des methodes de synchronisation. Ca me parait plutot normal...
    Par contre, il faut savoir que si tu as plusieurs Thread qui attendent (wait) sur un meme objet, lorsqu'il y aura un notify, il n'y a pas de garantie que la premiere qui attendait soit la premiere à passer. Mais dans ton cas, ca ne devrait pas etre un probleme.
    Sinon, tu peux aussi remplacer les Stack par des BlockingQueue. Cette derniere permet d'attendre la reception d'un element. Ca permettrait de t'affranchir des synchronisations...

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

Discussions similaires

  1. Problème de date décalée avec une requête via serveur lié
    Par Chabouille dans le forum Administration
    Réponses: 1
    Dernier message: 16/08/2012, 14h48
  2. Résultat commençant par un chiffre avec requête SELECT
    Par nicolas.pissard dans le forum Requêtes
    Réponses: 4
    Dernier message: 02/04/2010, 13h31
  3. Réponses: 10
    Dernier message: 26/11/2008, 23h18
  4. Réponses: 2
    Dernier message: 03/06/2007, 14h08
  5. [VB6][active x] faire du multi-thread avec vb
    Par pecheur dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 20/05/2003, 12h01

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