Liste Java synchronisée

J’ai une liste de tableaux pré-remplis. Et j’ai plusieurs threads qui vont supprimer des éléments de la liste de tableaux. Chaque thread appelle la méthode remove ci-dessous et supprime un élément de la liste. Le code suivant me donne-t-il un comportement cohérent?

ArrayList list = Collections.synchronizedList(new ArrayList()); void remove(Ssortingng item) { do something; (doesn't work on the list) list.remove(item); } 

Merci!

Oui, faites attention si vous parcourez également la liste, car dans ce cas, vous devrez vous synchroniser dessus. Du Javadoc :

Il est impératif que l’utilisateur synchronise manuellement sur la liste renvoyée lors d’une itération:

 List list = Collections.synchronizedList(new ArrayList()); ... synchronized (list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); } 

Ou, vous pouvez utiliser CopyOnWriteArrayList qui est plus lent pour les écritures, mais qui n’a pas ce problème.

Cela devrait être correct tant que vous n’avez pas besoin de la méthode “remove” pour être atomique.

En d’autres termes, si le “faire quelque chose” vérifie que l’élément apparaît plus d’une fois dans la liste par exemple, il est possible que le résultat de cette vérification soit incorrect au moment où vous atteignez la ligne suivante.

Assurez-vous également de synchroniser sur la liste lors de l’itération:

 synchronized(list) { for (Object o : list) {} } 

Comme mentionné par Peter Lawrey, CopyOnWriteArrayList peut vous simplifier la vie et offrir de meilleures performances dans un environnement hautement concurrentiel.

À partir des Collections#synchronizedList(List) javadoc

Renvoie une liste synchronisée (thread-safe) sauvegardée par la liste spécifiée. Afin de garantir l’access série, il est essentiel que tous les access à la liste de sauvegarde s’effectuent via la liste renvoyée … Il est impératif que l’utilisateur synchronise manuellement la liste renvoyée lors d’une itération. Ne pas suivre ces conseils peut entraîner un comportement non déterministe.

Vous pouvez avoir 2 problèmes différents avec les listes:
1) Si vous modifiez une itération dans un environnement mono, vous aurez une exception ConcurrentModificationException comme dans l’exemple suivant:

 List list = new ArrayList(); for (int i=0;i<5;i++) list.add("Hello "+i); for(String msg:list) list.remove(msg); 

Donc, pour éviter ce problème, vous pouvez faire:

 for(int i=list.size()-1;i>=0;i--) list.remove(i); 

2) Le second problème pourrait être l'environnement multi-threading. Comme mentionné ci-dessus, vous pouvez utiliser synchronisé (liste) pour éviter les exceptions.

Cela donnera un comportement cohérent pour les opérations d’ajout / suppression. Mais en itérant, vous devez explicitement synchroniser. Référer ce lien

Oui, cela fonctionnera correctement si vous avez synchronized la liste. Je vous suggère d’utiliser CopyOnWriteArrayList .

 CopyOnWriteArrayList cpList=new CopyOnWriteArrayList(new ArrayList()); void remove(Ssortingng item) { do something; (doesn't work on the list) cpList..remove(item); } 
 synchronized(list) { for (Object o : list) {} }