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 :

[THREAD][BLOCKINGQUEUE] Comment éviter un 'freeze' ?


Sujet :

Concurrence et multi-thread Java

  1. #1
    Membre Expert
    Avatar de narmataru
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    1 548
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Décembre 2002
    Messages : 1 548
    Par défaut [THREAD][BLOCKINGQUEUE] Comment éviter un 'freeze' ?
    Bonjour,
    J'ai un Thread T1 qui ajoute des données dans un ArrayBlockingQueue. J'en ai un autre T2 qui récupère les objet à partir de cette Queue.
    Comment faire pour éviter que T2 ne se bloque en demant à la queue de lui fournir encore un objet alros que T1 n'a plus rien à ajouter ?

    merci

  2. #2
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Salut,

    Tu peux utiliser la méthode poll() à la place de take(), qui permet de définir un timeout...

    a++

  3. #3
    Membre Expert
    Avatar de narmataru
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    1 548
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Décembre 2002
    Messages : 1 548
    Par défaut
    ouais mais je trouve pas ça très propre car si mon traitement dans T1 prend plus de temps que prévu il rique d'y avoir des soucis
    Mais je garde cette solution sous le coude, merci

  4. #4
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Quelques solutions :
    • Si tu connais à l'avance le nombre d'objet que ton thread T1 va passer à T2, il suffit de partager cette information entre les deux threads...
    • Tu peux utiliser un objet "marqueur" qui sera envoyé systématiquement à la fin par le producteur. Donc ton thread consommateur devra vérifier l'objet recu avant de le traiter :
    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
            final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(5);
            final String END = new String("END");
     
            Thread productor = new Thread("Productor") {
                @Override
                public void run() {
                    System.out.println(getName() + " : START");
                    Random r = new Random();
                    for (int i=0; i<5; i++) {
                        // Simule le traitement long (entre 0 et 5 secondes) :
                        try {
                            Thread.sleep( r.nextInt(5000) );
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
     
                        String data = "Ligne " + i;
                        System.out.println(getName() + " --> " + data);
                        queue.offer(data);
                    }
                    queue.offer(END);
                    System.out.println(getName() + " : FIN");
                }
            };
     
     
            Thread consumer = new Thread("Consumer") {
                @Override
                public void run() {
                    System.out.println(getName() + " : START");
                    while(true) {
                        try {
                            String data = queue.take();
                            // Si on est arrivé à la fin "on quitte"
                            if (data==END) {
                                break;
                            }
                            // Sinon on traite les données :
                            System.out.println(getName() + "  <-- " + data);
     
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(getName() + " : FIN");
                }
            };
     
            productor.start();
            consumer.start();
    • Sinon tu peux utiliser la méthode poll() avec un timeout, et le coupler avec un Semaphore : le Semaphore est acquis avant de lancer les deux threads, et ton thread T1 ne le libère qu'à la fin de son traitement. Ainsi lorsque ton thread T2 recois un timeout sur la méthode poll(), il doit vérifier l'état du Semaphore pour continuer ou pas :
    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
            final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(5);
            final Semaphore semaphore = new Semaphore(1);
            semaphore.acquire();
     
            Thread productor = new Thread("Productor") {
                @Override
                public void run() {
                    System.out.println(getName() + " : START");
                    Random r = new Random();
                    for (int i=0; i<5; i++) {
                        // Simule le traitement long (entre 0 et 5 secondes) :
                        try {
                            Thread.sleep( r.nextInt(5000) );
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
     
                        String data = "Ligne " + i;
                        System.out.println(getName() + " --> " + data);
                        queue.offer(data);
                    }
                    semaphore.release(); // libération de la sémaphore
                    System.out.println(getName() + " : FIN");
                }
            };
     
     
            Thread consumer = new Thread("Consumer") {
                @Override
                public void run() {
                    System.out.println(getName() + " : START");
                    while(true) {
                        try {
                            String data = queue.poll(500, TimeUnit.MILLISECONDS);
                            // Si on recoit des données on les traite :
                            if (data!=null) {
                                System.out.println(getName() + "  <-- " + data);
                            }
                            // Sinon on tente d'aquerir le semaphore
                            // pour savoir si le producteur est fini :
                            if (data==null && semaphore.tryAcquire()) {
                                break;
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(getName() + " : FIN");
                }
            };
     
            productor.start();
            consumer.start();
    a++

  5. #5
    Membre Expert
    Avatar de narmataru
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    1 548
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Décembre 2002
    Messages : 1 548
    Par défaut
    Merci beaucoup adiGuba !
    ta dernière solution est, je pense, la meilleur
    J'avas pensé utiliser un objet marqueur, mais le type d'objet que j'ajoute dans la queue ne le permet pas (à moins que je ne fasse une Queue<Object> mais je préfère Queue<MonObject>)

    T'es un chef adiGuba

  6. #6
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par narmataru
    J'avas pensé utiliser un objet marqueur, mais le type d'objet que j'ajoute dans la queue ne le permet pas (à moins que je ne fasse une Queue<Object> mais je préfère Queue<MonObject>)
    Pourquoi ? Tu peux très bien utiliser un MonObject comme marqueur puisque la comparaison s'effectues sur les références et non pas les valeurs...

    a++

  7. #7
    Membre Expert
    Avatar de narmataru
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    1 548
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Décembre 2002
    Messages : 1 548
    Par défaut
    Ok j'avas pas fait attention que c'était la référence qui était testée et non la valeur
    Mais je préfère quand même la seconde méthode qui est utilise des vrai system de synchronisation

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

Discussions similaires

  1. [C#] Plusieurs Thread pour éviter le freeze du chargement
    Par mister3957 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 15/09/2006, 19h00
  2. Comment éviter les doublons dans ma table
    Par einegel dans le forum Bases de données
    Réponses: 3
    Dernier message: 09/11/2004, 12h18
  3. [TEdit] Comment éviter le bip ?
    Par portu dans le forum Composants VCL
    Réponses: 4
    Dernier message: 01/10/2004, 12h01
  4. Réponses: 4
    Dernier message: 28/07/2004, 10h42
  5. [eclipse 2.1][compilation] Comment éviter...
    Par ftrifiro dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 29/06/2004, 16h16

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