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

Collection et Stream Java Discussion :

Exception "ConcurrentModificationException" et les ArrayList


Sujet :

Collection et Stream Java

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2007
    Messages : 152
    Points : 81
    Points
    81
    Par défaut Exception "ConcurrentModificationException" et les ArrayList
    Bonjour,
    Je débute en Java. Je tente de faire fonctionner un petit programme mais j'ai une exception "ConcurrentModificationException" lors de la modification de mes listes. Je sais que cette exception est générée lorsque l'on parcoure une liste par un thread et on l'a modifie avec un autre mais je n'arrive pas à résoudre le problème :
    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
    package test;
     
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.List;
     
    public class MonThread implements Runnable {
     
    	public List<InfoToSend> listInfo = Collections
    			.synchronizedList(new ArrayList<InfoToSend>());
    	public List<InfoToSend> listInfoTmpAdd = Collections
    			.synchronizedList(new ArrayList<InfoToSend>());
    	public List<InfoToSend> listInfoTmpDelete = Collections
    			.synchronizedList(new ArrayList<InfoToSend>());
    	private static boolean stop = true;
     
    	public MonThread(List<InfoToSend> list) {
    		this.listInfo = list;
    	}
     
    	@Override
    	public void run() {
    		synchronized (listInfo) {
     
    			while (stop) {
     
    				Iterator<InfoToSend> it = this.listInfo.iterator();
    				while (it.hasNext()) {
    					InfoToSend info = it.next();
    					System.out.println("Index : " + info.getIndex() + " Seq : "
    							+ info.getSeq() + " Desc : " + info.getDesc());
    				}
     
    				stop = false;
    			}
     
    		}
     
    	}
     
    	public void delete(int seq) {
     
    		listInfoTmpDelete.clear();
    		listInfoTmpDelete.addAll(listInfo);
    		Iterator<InfoToSend> it = this.listInfoTmpDelete.iterator();
     
    		while (it.hasNext()) {
    			InfoToSend info = it.next();
    			if (info.getSeq() == seq) {
    				listInfoTmpDelete.remove(info);
    			}
    		}
    		listInfo.addAll(listInfoTmpDelete);
    	}
     
    	public void add(InfoToSend alerte) {
    		listInfoTmpAdd.clear();
    		listInfoTmpAdd.addAll(listInfo);
    		listInfoTmpAdd.add(alerte);
    		listInfo.addAll(listInfoTmpAdd);
    	}
     
    }
    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
     
    package test;
     
    public class InfoToSend {
     
    	public int seq;
    	public int index;
    	public String desc;	
     
    	public int getSeq() {
    		return seq;
    	}
    	public void setSeq(int seq) {
    		this.seq = seq;
    	}
    	public int getIndex() {
    		return index;
    	}
    	public void setIndex(int index) {
    		this.index = index;
    	}
    	public String getDesc() {
    		return desc;
    	}
    	public void setDesc(String desc) {
    		this.desc = desc;
    	}
     
    }
    et ma méthode main :
    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
    package test;
     
    import java.util.ArrayList;
    import java.util.List;
     
    public class TestCase {		
     
     
    	public TestCase() {
    	}
     
    	public static void main(String[] args) {
     
    		List<InfoToSend> listInfos = new ArrayList<InfoToSend>();
     
    		InfoToSend info1 = new InfoToSend();		
    		info1.setIndex(1);
    		info1.setSeq(10);
    		info1.setDesc("Info1");
     
    		InfoToSend info2 = new InfoToSend();		
    		info2.setIndex(2);
    		info2.setSeq(20);
    		info2.setDesc("Info2");
    		listInfos.add(info1);
    		listInfos.add(info2);
     
    		MonThread t1 = new MonThread(listInfos);
    		t1.run();
     
    		InfoToSend info3 = new InfoToSend();		
    		info3.setIndex(2);
    		info3.setSeq(99);
    		info3.setDesc("Info3");	
     
    		t1.add(info3);
    		t1.delete(99);		
     
    	}
     
    }
    Merci pour votre aide.

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    vous devez protéger vos objets pour qu'ils ne s'exécutent pas en même temps. Par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    synchronized(this.listInfo){
    				Iterator<InfoToSend> it = this.listInfo.iterator();
    				while (it.hasNext()) {
    					InfoToSend info = it.next();
    					System.out.println("Index : " + info.getIndex() + " Seq : "
    							+ info.getSeq() + " Desc : " + info.getDesc());
    				}
    }
    et
    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
    	public void delete(int seq) {
               synchronized(this.listInfo){
    		listInfoTmpDelete.clear();
    		listInfoTmpDelete.addAll(listInfo);
    		Iterator<InfoToSend> it = this.listInfoTmpDelete.iterator();
     
    		while (it.hasNext()) {
    			InfoToSend info = it.next();
    			if (info.getSeq() == seq) {
    				listInfoTmpDelete.remove(info);
    			}
    		}
    		listInfo.addAll(listInfoTmpDelete);
               }
    	}
     
    	public void add(InfoToSend alerte) {
               synchronized(this.listInfo){
    		listInfoTmpAdd.clear();
    		listInfoTmpAdd.addAll(listInfo);
    		listInfoTmpAdd.add(alerte);
    		listInfo.addAll(listInfoTmpAdd);
               }
    	}
    Deuxièmement, dans le delete, vous avez une erreur supplémentaire, vous effacez de la liste alors que vosu itérez dessus, ça va d'office casser, thread ou pas thread. Le bon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    		while (it.hasNext()) {
    			InfoToSend info = it.next();
    			if (info.getSeq() == seq) {
    				it.remove(); // on efface l'item récupéré en dernier
    			}
    		}
    Enfin, pour démarrer des thread, c'est la méthode start() et non pas run() qu'il faut appeler. Start crée un thread, le démarrer, et dans ce thread appelle la méthode run(). run() ne fait que ce que vous lui dites de faire.

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2007
    Messages : 152
    Points : 81
    Points
    81
    Par défaut
    Bonjour et merci pour votre réponse. En effet, j'ai fait une boulette dans le delete et dans le démarrage du thread mais ce que je ne comprend pas c'est que les listes sont déclarées synchronisées avec ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    public  List<InfoToSend> listInfo = Collections
    			.synchronizedList(new ArrayList<InfoToSend>());
    ça ne suffit pas?
    Merci pour votre aide.


    Citation Envoyé par tchize_ Voir le message
    vous devez protéger vos objets pour qu'ils ne s'exécutent pas en même temps. Par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    synchronized(this.listInfo){
    				Iterator<InfoToSend> it = this.listInfo.iterator();
    				while (it.hasNext()) {
    					InfoToSend info = it.next();
    					System.out.println("Index : " + info.getIndex() + " Seq : "
    							+ info.getSeq() + " Desc : " + info.getDesc());
    				}
    }
    et
    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
    	public void delete(int seq) {
               synchronized(this.listInfo){
    		listInfoTmpDelete.clear();
    		listInfoTmpDelete.addAll(listInfo);
    		Iterator<InfoToSend> it = this.listInfoTmpDelete.iterator();
     
    		while (it.hasNext()) {
    			InfoToSend info = it.next();
    			if (info.getSeq() == seq) {
    				listInfoTmpDelete.remove(info);
    			}
    		}
    		listInfo.addAll(listInfoTmpDelete);
               }
    	}
     
    	public void add(InfoToSend alerte) {
               synchronized(this.listInfo){
    		listInfoTmpAdd.clear();
    		listInfoTmpAdd.addAll(listInfo);
    		listInfoTmpAdd.add(alerte);
    		listInfo.addAll(listInfoTmpAdd);
               }
    	}
    Deuxièmement, dans le delete, vous avez une erreur supplémentaire, vous effacez de la liste alors que vosu itérez dessus, ça va d'office casser, thread ou pas thread. Le bon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    		while (it.hasNext()) {
    			InfoToSend info = it.next();
    			if (info.getSeq() == seq) {
    				it.remove(); // on efface l'item récupéré en dernier
    			}
    		}
    Enfin, pour démarrer des thread, c'est la méthode start() et non pas run() qu'il faut appeler. Start crée un thread, le démarrer, et dans ce thread appelle la méthode run(). run() ne fait que ce que vous lui dites de faire.

  4. #4
    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
    Citation Envoyé par allouchi Voir le message
    ça ne suffit pas?
    Non, pas si tu utilises des Iterator sur cette liste. Ça ne vas pas deviner automagiquement où il faut synchroniser.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2007
    Messages : 152
    Points : 81
    Points
    81
    Par défaut
    Ok merci pour les conseils je tenterai la chose lundi matin et je vous dirais.


    Citation Envoyé par thelvin Voir le message
    Non, pas si tu utilises des Iterator sur cette liste. Ça ne vas pas deviner automagiquement où il faut synchroniser.

  6. #6
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2007
    Messages : 152
    Points : 81
    Points
    81
    Par défaut
    Ok merci ça marche!!!

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

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