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 :

[Langage] Declaration d'une FIFO de tableaux d'int thread safe java (comportement etrange)


Sujet :

Concurrence et multi-thread Java

  1. #1
    Candidat au Club
    Homme Profil pro
    Analyse système
    Inscrit en
    Décembre 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyse système

    Informations forums :
    Inscription : Décembre 2014
    Messages : 2
    Points : 2
    Points
    2
    Par défaut [Langage] Declaration d'une FIFO de tableaux d'int thread safe java (comportement etrange)
    bonjour,

    En java, J'essaye d'utiliser une FIFO (queue) dont chaque "element" est un tableau d'int. Cette fifo devant etre écrite / lue par deux threads differents, je me suis tourné vers une ConcurrentLinkedQueue . Tout va bien tant que je déclare des elements simples type "Integer" ou "String", mais je ne comprends plus le fonctionnement quand je veux déclarer des tableaux de int ( int[] ) pour chaque element. La FIFO me renvoit "comme le dernier élément, je dois me gaufrer dans la récupération (poll), comme si le "pointeur" du tableau de la fifo lue n'etait pas bien interpreté..

    je vous met un exemple de code simple que j'ai dérivé d'un example :

    il consiste juste à déclarer un tableau de int, dont je vais modifier le 2ème element à chaque écrite dans la queue fifo. J'écris la fifo rapidement et je la lis lentement. on voit que le nombre d'elements est correct (le poll vide bien la fifo) mais le contenu rapatrié par poll semble erroné (le 2eme element du tableau rappatrié par poll ne contient pas le bon numero, il contient systematiquement le dernier element écrit et plusieurs fois de suite (ce n'est pas non plus une pile!):

    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
     
    import java.util.concurrent.*;
     
    public class ConcurrentLinkedQueueExample {
       public static void main(String[] args) {
          ConcurrentLinkedQueue<int[]> queue = new ConcurrentLinkedQueue<int[]>();
          Thread producer = new Thread(new Producer(queue));
          Thread consumer = new Thread(new Consumer(queue));
          producer.start();
          consumer.start();
      }
    }
     
    // the producer puts strings on the queue 
    class Producer implements Runnable {
      private int[] ligneecrite;
       ConcurrentLinkedQueue<int[]> queue;
       Producer(ConcurrentLinkedQueue<int[]> queue){
          this.queue = queue;
       }
       public void run() {
    	  ligneecrite=new int [10];
          System.out.println("Producer Started");
          try {
             for (int i = 1; i < 20; i++) {
            	 ligneecrite[0] = 0;
            	 ligneecrite[1] = i;
            	 ligneecrite[2] = 0;
                queue.add(ligneecrite);
                System.out.println("++ > Added: id contenu dans le 2eme element " + ligneecrite[1]);
                Thread.currentThread().sleep(200);
             }
          } catch (Exception ex) {
             ex.printStackTrace();
          }
       }
    }
     
    // the consumer removes strings from the queue
    class Consumer implements Runnable {
    	int[] lignelue;
       ConcurrentLinkedQueue<int[]> queue;
       Consumer(ConcurrentLinkedQueue<int[]> queue){
          this.queue = queue;
       }
       public void run() {
          String str;
          System.out.println("Consumer Started");
          for (int x = 0; x < 20; x++) {
             while ((lignelue = queue.poll()) != null) {
                System.out.println("---- > Removed: id contenu dans le 2eme element " + lignelue[1]);
             }
             try {
                Thread.currentThread().sleep(500);
             } catch (Exception ex) {
                ex.printStackTrace();
             }
          }
       }
    }

    cela donne :


    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
    Producer Started
    Consumer Started
    ++ > Added: id contenu dans le 2eme element 1
    ---- > Removed: id contenu dans le 2eme element 1
    ++ > Added: id contenu dans le 2eme element 2
    ++ > Added: id contenu dans le 2eme element 3
    ---- > Removed: id contenu dans le 2eme element 3
    ---- > Removed: id contenu dans le 2eme element 3
    ++ > Added: id contenu dans le 2eme element 4
    ++ > Added: id contenu dans le 2eme element 5
    ---- > Removed: id contenu dans le 2eme element 5
    ---- > Removed: id contenu dans le 2eme element 5
    ++ > Added: id contenu dans le 2eme element 6
    ---- > Removed: id contenu dans le 2eme element 6
    ++ > Added: id contenu dans le 2eme element 7
    ++ > Added: id contenu dans le 2eme element 8
    ---- > Removed: id contenu dans le 2eme element 8
    ---- > Removed: id contenu dans le 2eme element 8
    ++ > Added: id contenu dans le 2eme element 9
    ++ > Added: id contenu dans le 2eme element 10
    ---- > Removed: id contenu dans le 2eme element 10
    ---- > Removed: id contenu dans le 2eme element 10
    ++ > Added: id contenu dans le 2eme element 11
    ++ > Added: id contenu dans le 2eme element 12
    ++ > Added: id contenu dans le 2eme element 13
    ---- > Removed: id contenu dans le 2eme element 13
    ---- > Removed: id contenu dans le 2eme element 13
    ---- > Removed: id contenu dans le 2eme element 13
    ++ > Added: id contenu dans le 2eme element 14
    ++ > Added: id contenu dans le 2eme element 15
    ---- > Removed: id contenu dans le 2eme element 15
    ---- > Removed: id contenu dans le 2eme element 15
    ++ > Added: id contenu dans le 2eme element 16
    ++ > Added: id contenu dans le 2eme element 17
    ++ > Added: id contenu dans le 2eme element 18
    ---- > Removed: id contenu dans le 2eme element 18
    ---- > Removed: id contenu dans le 2eme element 18
    ---- > Removed: id contenu dans le 2eme element 18
    ++ > Added: id contenu dans le 2eme element 19
    ---- > Removed: id contenu dans le 2eme element 19

    > Fonctionnement identique avec Java 1.6 et Java 1.7.


    je sèche un peu.... auriez vous une piste ? une autre façon de faire cette fifo de tableaux de int thread safe ?


    merci


    Merci de votre aide;;

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Mais... il n'y a qu'un seul tableau int[] dans ton code. Tu ne fais qu'un seul new...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Modérateur
    Avatar de Alkhan
    Homme Profil pro
    ingénieur full stack
    Inscrit en
    Octobre 2006
    Messages
    1 232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : ingénieur full stack

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 232
    Points : 2 061
    Points
    2 061
    Par défaut
    bonjour,

    je suis entièrement d'accord avec ce que tu as dis @thelvin, mais je pense qu'une précision s'impose pour que les débutants comprennent !

    Le fait de faire un "queue.add(ligneecrite);" fait bien que la FIFO contiendra bien n éléments.
    Cependant du fait que le tableau est créé a l’extérieur de la boucle la FIFO contiendra n fois la référence du même tableau, donc à la fin de la boucle tout les nœuds de la FIFO auront les même valeur puisque qu'il n'y a en réalité qu'un seul tableau.
    Il faut donc, pour que cela fonctionne, mettre la création du tableau dans la boucle et c'est seulement a cette condition que tu aura n tableau différent.
    Il n'y a pas de problème, il n'y a que des solutions.
    Cependant, comme le disaient les shadoks, s'il n'y a pas de solution, c'est qu'il n'y a pas de problème.
    Si toutefois le problème persiste, la seule solution restante est de changer le périphérique qui se trouve entre la chaise et l'écran

    Mes Articles : Mon premier article est sur le language D
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Candidat au Club
    Homme Profil pro
    Analyse système
    Inscrit en
    Décembre 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyse système

    Informations forums :
    Inscription : Décembre 2014
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    merci,si j'ai bien compris, il a suffit de remplacer

    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 run() {
    	  ligneecrite=new int [10];
          System.out.println("Producer Started");
          try {
             for (int i = 1; i < 20; i++) {
            	 ligneecrite[0] = 0;
            	 ligneecrite[1] = i;
            	 ligneecrite[2] = 0;
                queue.add(ligneecrite);
                System.out.println("++ > Added: id contenu dans le 2eme element " + ligneecrite[1]);
                Thread.currentThread().sleep(200);
             }
          } catch (Exception ex) {
             ex.printStackTrace();
          }
    par

    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 run() {
          System.out.println("Producer Started");
          try {
             for (int i = 1; i < 20; i++) {
            	 ligneecrite=new int [10];
            	 ligneecrite[0] = 0;
            	 ligneecrite[1] = i;
            	 ligneecrite[2] = 0;
                queue.add(ligneecrite);
                System.out.println("++ > Added: id contenu dans le 2eme element " + ligneecrite[1]);
                Thread.currentThread().sleep(200);
             }
          } catch (Exception ex) {
             ex.printStackTrace();
          }

    merci ! (ça marche!)


    du coup, est ce que la mémoire est correctement gérée ensuite, à mesure que je fais les poll ? Est ce qu'il faut faire quelque chose de particulier pour liberer les espaces mémoires créés par le NEW ?

  5. #5
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Points : 7 083
    Points
    7 083
    Par défaut
    Java garde en mémoire les objets tant qu'ils sont référencés. Et les libère ensuite selon son "bon vouloir" (au bout d'un certains temps ou quand la mémoire vient à manquer).

    Dans ton cas, il est d'abord référencé par le producteur dans la boucle puis passer dans la file. Cependant le producteur garde la référence du dernier élément (utilisation d'un attribut).
    Puis le consommateur retire la référence de la file et la stocke également dans un attribut. Le consommateur garde donc également la référence du dernier élément.

    Enfin le programme s'arrête et tout est libéré

    Tu devrais "déplacer" ton attribut en tant que variable locale (dans la boucle pour le producteur, juste avant pour le consommateur).
    Java : Cours et tutoriels - FAQ - Java SE 8 API - Programmation concurrente
    Ceylon : Installation - Concepts de base - Typage - Appels et arguments

    ECM = Exemple(reproduit le problème) Complet (code compilable) Minimal (ne postez pas votre application !)
    Une solution vous convient ? N'oubliez pas le tag
    Signature par pitipoisson

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

Discussions similaires

  1. [langage] longueur d'une chaine lue ds un fichier
    Par perlaud dans le forum Langage
    Réponses: 6
    Dernier message: 30/06/2004, 22h36
  2. [langage] Comportement étrange d'une variable
    Par Spaz dans le forum Langage
    Réponses: 6
    Dernier message: 23/04/2004, 11h29
  3. Réponses: 6
    Dernier message: 04/03/2004, 09h35
  4. Réponses: 3
    Dernier message: 21/01/2004, 08h47
  5. Réponses: 2
    Dernier message: 19/08/2003, 18h04

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