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 :

[Threads] Implémenter une pile de processus


Sujet :

Java

  1. #1
    Invité
    Invité(e)
    Par défaut [Threads] Implémenter une pile de processus
    Bonjour,

    Je tente de créer un "gestionnaire de processus". Ce gestionnaire doit posséder une pile de processus en attente. Le gestionnaire peux faire tourner au maximum N processus simultanés.

    Pour cela j'ai ecris 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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    // pile est une LinkedList
    // Process implémente Runnable
    public void run() {
            run = true;
    
            while ( run ) {
                
                if ( pile.size()>0 && getActiveCount()<MAX_PROCESS ) {
                    try {
                        Process p = pile.getFirst();
                        new Thread(p).start();
                        pile.removeFirst();
                    } 
                    catch ( NoSuchElementException e ) {}
                } 
                else {            
                    try {
                        synchronized (this) {
                            System.out.println("wait : \n\t" + 
                                    "size : " + p.size() + "\n\t" +
                                    "actifs : " + getActiveCount()
                                    );
                            wait();                         
                        }
                    }   
                    catch ( InterruptedException e ) {
                        e.printStackTrace();
                        run = false;
                    }                
                }
            }              
        }
    
    //Lorsqu'un processus est ajouté à la pile ou qu'un processus est terminé, je //fais un notifyAll.
    // La gestionnaire implémente ProcessListener (qui écoute les évènements d'un processus)
    
     public void register(Process p) {
            if ( p== null)
                throw new NullPointerException();
            
            synchronized (this) {
                p.addProcessListener(this);
                pile.addLast(p);
                fireProcessAdded(p);            
            }
        }
    
    public void processFinished(Process p) {
            pile.remove(p);
            synchronized (this) {
                actifs --;
                notifyAll();
            }
    // Il y à aussi un listener pour le gestionnaire qui doit-être prévenu lorsqu'une conversion est terminée.
            fireProcessFinished(p);
        }
    Malheureusement, je dois ajouter troisProcesss avant que le gestionnaire ne commence à les démarrer.

    run:
    Active count 0
    wait :
    size : 0
    actifs : 0
    Enregistre le process : PremierProcess
    Active count 0
    wait :
    size : 0
    actifs : 0
    PremierProcess démarrer.
    PremierProcess essais : 13

    Enregistre le process: SecondProcess
    Active count 1
    wait :
    size : 0
    actifs : 1
    SecondProcess démarrer.
    SecondProcess essais : 7

    Enregistre le process: TroisiemeProcess
    Active count 2
    wait :
    size : 1
    actifs : 2
    tentative 0 de 7
    tentative 0 de 13
    tentative 1 de 7
    tentative 1 de 13
    ....

    SecondProcess termine apres 1185284414699 ms
    SecondProcess terminé.
    Active count 1
    Active count 1
    wait :
    size : 0
    actifs : 1
    TroisiemeProcess démarrer.
    TroisiemeProcess essais : 4

    SecondProcess FINISH

    tentative 9 de 13
    tentative 0 de 4
    ...
    TroisiemeProcess termine apres 1185284414746 ms
    TroisiemeProcess terminé.
    Active count 1
    wait :
    size : 0
    actifs : 1
    TroisiemeProcess FINISH

    tentative 11 de 13
    tentative 12 de 13
    PremierProcess termine apres 1185284414746 ms
    PremierProcess terminé.
    Active count 0
    wait :
    size : 0
    actifs : 0
    PremierProcess FINISH
    Bien que l'on voit le message du listener signalant que le process est démarré, rien ne se passe tant qu'il n'y à pas 3 process ajoutés.

    Voici le code run() d'un Process :
    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
     public void run() {
     
            //System.out.println(name + " START ");
            fireConverterStarted();
            int essais = (int) ((Math.random()*10)*2);
     
            System.out.println(name + " essais : " + essais);
            JFrame frm = new JFrame("Tentative");
            frm.setLocationByPlatform(true);
            frm.setSize(100,200);
            frm.setVisible(true);
     
            for (int i=0; i<essais; i++) {
                System.out.println("\t tentative " + i + " de " + essais);
                frm.getContentPane().removeAll();
                frm.getContentPane().add(new JLabel("Tentative " + i + " de " + essais));
                frm.validate();
                try {
                    new Socket("nonhost", 9999);
     
                } catch ( Exception e) {}
            }
            frm.setVisible(false);
     
            fireConverterFinished();
            frm.dispose();
            System.out.println(name + " FINISH ");

    Merci
    Dernière modification par Invité ; 24/07/2007 à 15h46.

  2. #2
    Membre actif Avatar de coco62
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 237
    Points : 278
    Points
    278
    Par défaut
    Il me semble que le jdk 1.5 propose avec les nouvelles API concurrent ce type de fonctionnement
    http://java.sun.com/j2se/1.5.0/docs/...Executors.html

  3. #3
    Invité
    Invité(e)
    Par défaut
    Oui il semble que cela puisse m'aider mais mon problème est sur un simple "exercice de style". J'aimerais donc trouver la cause du problème pour le plaisir de jouer avec les Threads.

    Merci pour l'info, ça semble très intéressant.

  4. #4
    Membre émérite
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Points : 2 582
    Points
    2 582
    Par défaut
    Je ne peux pas expliquer précisement, mais je vois des maladresses qui rendent difficiles le suivi de ton code.

    • Beaucoup de choses s'appellent run, ce qui fait qu'on ne sait plus très bien qui est quoi. Essaie de réserver le terme run à la méthode d'exécution d'un thread, ce qui rendra ton code plus intuitif pour nous, et pour moi, en particulier.
    • Je ne suis pas sûr que les synchronisations soient bien faites, surtout si l'objet verrou est lui même un thread (puisqu'il comporte une méthode run...). J'avoue ne même pas savoir comment la JVM se débrouille dans ce cas là.
    • Simplifie ton code au maximum lorsque tu galères pour le faire fonctionner, et évite les swing, surtout que à ce que je comprends tu ne fais pas gaffe à te caler sur l'Event Dispatching Thread pour lancer tes fenêtres, ce qui peut perturber tout le fonctionnement.
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  5. #5
    Invité
    Invité(e)
    Par défaut
    J'ai essayé d'utiliser un objet pour faire mes synchronisations mais j'ai une java.lang.IllegalMonitorStateException.
    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
     
    ...
    private Object verrou = new Object();
    ...
     public void run() {
            actif = true;
     
     
            while ( actif ) {
     
                if ( converters.size()>0 && getActiveCount()<MAX_CONVERTERS ) {
                    try {
                        Converter converter = converters.getFirst();
                        new Thread(converter).start();
                        converters.removeFirst();
                    } 
                    catch ( NoSuchElementException e ) {}
                } 
                else {            
                    try {
                        synchronized (verrou) {
                            System.out.println("wait : \n\t" + 
                                    "size : " + converters.size() + "\n\t" +
                                    "actifs : " + getActiveCount()
                                    );
                            wait();                         
                        }
                    }   
                    catch ( InterruptedException e ) {
                        e.printStackTrace();
                        actif = false;
                    }                
                }
            }
    }
    ...

    J'ai également commenté la partie Swing. Elle était la simplement pour avoir un meilleur aperçu de ce qui se passait.

  6. #6
    Membre émérite
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Points : 2 582
    Points
    2 582
    Par défaut
    J'ai l'impression qu'il te manque les bases élémentaires de manipulation des threads !

    Si tu comprends l'anglais Lesson: Concurrency, sinon Les Threads multiples et plein d'autres.

    Sinon il est utile d'indiquer la ligne où se produit l'erreur, je présume que la tienne vient d'un thread que tu relances, ou qui est en cours d'exécution, ou je ne sais quoi.
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  7. #7
    Membre confirmé
    Inscrit en
    Mai 2007
    Messages
    335
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 335
    Points : 511
    Points
    511
    Par défaut
    Bonjour,
    Oui, il faut maitriser les wait/notify, l'algorithme de Thread en réalisant un petit diagramme de séquence.
    Là j'ai du mal à comprendre comment ça se passe: si tu ne "notify" pas à l'enregistrement d'un Process, comment ton while va se débloquer? où est ce que tu incrémente le compte d'actif que tu décrémente sur le désenregistrement?

    (j'espère que tu ne lance pas le run() à chaque fois que tu enregistre un Process?)
    pour t'assurer de ne pas rester bloqué sur la wait, tu peux mettre un temps d'attente "wait(1000)" par exemple pour 1 seconde.

    d'autre part, il faut faire le synchronized, wait et notify sur le même objet verrou, donc c'est synchronized(verrou){verrou.wait(timeout);...

    et idem, tu fera un verrou.notify();

    petite remarque, pour débuter sur les Thread, peut-être que les sémaphore sont plus simple à gérer: ça remplit exactement la fonction ont tu a besoin: ne locker qu'à partir de n demandes de ressource (ici de Thread)

  8. #8
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par deltree
    Là j'ai du mal à comprendre comment ça se passe: si tu ne "notify" pas à l'enregistrement d'un Process, comment ton while va se débloquer? où est ce que tu incrémente le compte d'actif que tu décrémente sur le désenregistrement?
    Je notify à chaque ajout dans fireConverteedAdded(..)
    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
     
    // Ajoute un processus 
    public void register(Converter converter) {
            if ( converter== null)
                throw new NullPointerException("un convertisseur null ne peux pas être enregistré.");
     
            synchronized (verrou) {
                converter.addConverterListener(this);
                converters.addLast(converter);
                fireConverterAdded(converter);            
            }
        }
     
    // ...
     protected void fireConverterAdded(Converter converter) {
            synchronized (this) {
                notifyAll();
            }
            for (ConverterManagerListener listener : getManagerListeners() ) {
                listener.converterAdded(converter);
            }
        }
    J'ai des listeners sur les convertisseurs qui me peremttent de savoir lorsqu'il sont démarrés et terminés, c'est la que j'incrémente ou décrémente mon compteur d'actifs
    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
      public void converterFinished(Converter converter) {
            converters.remove(converter);
            synchronized (verrou) {
                actifs --;
                notifyAll();
            }
            fireConverterFinished(converter);
        }
     
        public void converterStarted(Converter converter) {
            synchronized (this) {
                actifs ++;
            }
            fireConverterStarted(converter);
        }
    Citation Envoyé par deltree
    pour t'assurer de ne pas rester bloqué sur la wait, tu peux mettre un temps d'attente "wait(1000)" par exemple pour 1 seconde.

    d'autre part, il faut faire le synchronized, wait et notify sur le même objet verrou, donc c'est synchronized(verrou){verrou.wait(timeout);...

    et idem, tu fera un verrou.notify();
    Ok, je vais tester cela et jetter un oeil aux articles. Merci pour les infos, je vous tiens informés.

Discussions similaires

  1. Implémentation d'une pile et d'une file
    Par adrian07 dans le forum Débuter
    Réponses: 5
    Dernier message: 12/06/2010, 14h41
  2. [THREAD] Implémentation d'une attente
    Par Ephasme dans le forum Interfaces Graphiques en Java
    Réponses: 4
    Dernier message: 13/05/2008, 09h31
  3. implémentation d'une pile avec 2 files
    Par seb__ dans le forum Langage
    Réponses: 5
    Dernier message: 23/09/2006, 13h59
  4. Thread avec une fonction membre d'une classe
    Par SteelBox dans le forum Windows
    Réponses: 6
    Dernier message: 01/03/2004, 01h15

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