149 votes

ConcurrentModificationException et un HashMap

Je persiste avec des objets en utilisant JPA. L'objet Main a une relation un-plusieurs propriétaire avec un autre objet. L'autre objet est stocké dans un HashMap. Quel type de synchronisation résoudrait ce problème? Cela semble se produire à des moments complètement aléatoires et est très imprévisible. Voici l'exception que je reçois:

 Exception in thread "pool-1-thread-1" java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
        at java.util.HashMap$ValueIterator.next(Unknown Source)
        at org.hibernate.collection.AbstractPersistentCollection$IteratorProxy.next(AbstractPersistentCollection.java:555)
        at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
        at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
        at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
        at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
        at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
 

286voto

Robin Points 15032

Ce n'est pas un problème de synchronisation. Cela se produira si la collection sous-jacente qui est itérée est modifiée par autre chose que l'Iterator lui-même.

 Iterator it = map.entrySet().iterator();
while (it.hasNext())
{
   Entry item = it.next();
   map.remove(item.getKey());
}
 

Cela lève une exception ConcurrentModificationException lorsque le it.hasNext () est appelé une deuxième fois.

La bonne approche serait

    Iterator it = map.entrySet().iterator();
   while (it.hasNext())
   {
      Entry item = it.next();
      it.remove();
   }
 

En supposant que cet itérateur supporte l'opération remove ().

84voto

Chochos Points 3364

Essayez d'utiliser un ConcurrentHashMap au lieu d'un simple HashMap

2voto

duffymo Points 188155

Cela ressemble moins à un problème de synchronisation Java qu’à un problème de verrouillage de base de données.

Je ne sais pas si l'ajout d'une version à toutes vos classes persistantes réglera ce problème, mais c'est l'une des façons qu'Hibernate peut fournir un accès exclusif aux lignes d'une table.

Peut-être que le niveau d'isolement doit être plus élevé. Si vous autorisez les "lectures incorrectes", vous devrez peut-être passer en mode sérialisable.

0voto

Javamann Points 1937

Essayez soit CopyOnWriteArrayList ou CopyOnWriteArraySet en fonction de ce que vous essayez de faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X