如何调试ConcurrentModificationException?
我遇到了ConcurrentModificationException,通过查看它,我看不出它为什么会发生的原因; 抛出exception的区域和修改集合的所有位置都被包围
synchronized (this.locks.get(id)) { ... } // locks is a HashMap;
我试图抓住讨厌的线程,但我所能指出的(通过在exception中设置断点)是抛出线程拥有监视器而另一个线程(程序中有两个线程)睡眠。
我该怎么办? 当遇到类似的线程问题时,您通常会做什么?
它可能与同步块无关。 当您在迭代其元素时修改集合时,经常会发生ConcurrentModificationException
。
List messages = ...; for (String message : messages) { // Prone to ConcurrentModificationException messages.add("A COMPLETELY NEW MESSAGE"); }
与上一篇文章类似,如果删除条目,则可能会出现同样的问题。 例如
for(String message : messages) { if (condition(message)) messages.remove(message); }
另一个常见的例子是清理Map。
可以使用Iterator明确解决此特定问题。
for(Iterator iter = messages.iterator(); iter.hasNext();) { String message = iter.next(); if (condition(message)) iter.remove(); // doesn't cause a ConcurrentModificationException }
有时您的应用程序可能复杂得太复杂,某些function可能会产生太多副作用。 另外,也许另一个线程确实对该列表做错了,你无法轻易找到。
对于我自己的问题,我编写了自己的列表系统,委托另一个列表,一旦锁定,所有其他修改抛出ConcurrentModificationException,因此错误的修改指令将在输出处获得exception。 它还可以检测上述错误。
import java.util。*; / ** *由IntelliJ IDEA创建。 *用户:francoiscassistat *日期:2010年7月12日 *时间:18:20:18 * * *可锁定列表,用于在列表上调试ConcurrentModificationException。 *可以使用setLocked(boolean)打开/关闭锁定。 *锁定时,对列表或迭代器的所有写访问都会获得ConcurrentModificationException。 *简单的使用案例: * * list.setLocked(true); * * for(Object o:list.iterator())//现在这不会得到ConcurrentModificationException,导致这个的另一个指令会抛出exception * {...} * * list.setLocked(false); * / 公共类LockableList实现List { protected class LockableListIterator实现Iterator { protected Iterator 迭代器; public LockableListIterator(Iterator iterator){ this.iterator = iterator; } public boolean hasNext(){ return iterator.hasNext(); } public E next(){ return iterator.next(); } public void remove(){ CHECKLOCK(); iterator.remove(); } } protected class LockableListListIterator实现ListIterator { protected ListIterator listIterator; public LockableListListIterator(ListIterator listIterator){ this.listIterator = listIterator; } public boolean hasNext(){ return listIterator.hasNext(); } public E next(){ return listIterator.next(); } public boolean hasPrevious(){ return listIterator.hasPrevious(); } public E previous(){ return listIterator.previous(); } public int nextIndex(){ return listIterator.nextIndex(); } public int previousIndex(){ return listIterator.previousIndex(); } public void remove(){ CHECKLOCK(); listIterator.remove(); } public void set(E e){ CHECKLOCK(); listIterator.set(E); } public void add(E e){ CHECKLOCK(); listIterator.add(E); } } protected class LockableListSubList实现List { protected List 列表; public LockableListSubList(List list){ this.list = list; } public int size(){ return list.size(); } public boolean isEmpty(){ return list.isEmpty(); } public boolean contains(Object o){ return list.contains(o); } public Iterator iterator(){ 返回新的LockableListIterator(list.iterator()); } public Object [] toArray(){ return list.toArray(); } public T [] toArray(T [] a){ return list.toArray(a); } public boolean add(E e){ CHECKLOCK(); return list.add(e); } public boolean remove(Object o){ CHECKLOCK(); return list.remove(o); } public boolean containsAll(Collection <?> c){ return list.containsAll(c); } public boolean addAll(Collection <?extends E> c){ CHECKLOCK(); return list.addAll(c); } public boolean addAll(int index,Collection <?extends E> c){ CHECKLOCK(); return list.addAll(index,c); } public boolean removeAll(Collection <?> c){ CHECKLOCK(); return list.removeAll(c); } public boolean retainAll(Collection <?> c){ CHECKLOCK(); return list.retainAll(c); } public void clear(){ CHECKLOCK(); list.clear(); } @覆盖 public boolean equals(Object o){ return list.equals(o); } @覆盖 public int hashCode(){ return list.hashCode(); } public E get(int index){ return list.get(index); } public E set(int index,E element){ CHECKLOCK(); return list.set(index,element); } public void add(int index,E element){ CHECKLOCK(); list.add(index,element); } public E remove(int index){ CHECKLOCK(); return list.remove(index); } public int indexOf(Object o){ return list.indexOf(o); } public int lastIndexOf(Object o){ return list.lastIndexOf(o); } public ListIterator listIterator(){ return new LockableListListIterator(list.listIterator()); } public ListIterator listIterator(int index){ return new LockableListListIterator(list.listIterator(index)); } public List subList(int fromIndex,int toIndex){ 返回新的LockableListSubList(list.subList(fromIndex,toIndex)); } } protected List 列表; protected boolean locked; public LockableList(List list){ this.list = list; locked = false; } public boolean isLocked(){ 返回锁定; } public void setLocked(boolean locked){ this.locked =已锁定; } protected void checkLock(){ 如果(锁定) 抛出新的ConcurrentModificationException(“Locked”); } public int size(){ return list.size(); } public boolean isEmpty(){ return list.isEmpty(); } public boolean contains(Object o){ return list.contains(o); } public Iterator iterator(){ 返回新的LockableListIterator(list.iterator()); } public Object [] toArray(){ return list.toArray(); } public T [] toArray(T [] a){ return list.toArray(a); } public boolean add(E e){ CHECKLOCK(); return list.add(e); } public boolean remove(Object o){ CHECKLOCK(); return list.remove(o); } public boolean containsAll(Collection <?> c){ return list.containsAll(c); } public boolean addAll(Collection <?extends E> c){ CHECKLOCK(); return list.addAll(c); } public boolean addAll(int index,Collection <?extends E> c){ CHECKLOCK(); return list.addAll(index,c); } public boolean removeAll(Collection <?> c){ CHECKLOCK(); return list.removeAll(c); } public boolean retainAll(Collection <?> c){ CHECKLOCK(); return list.retainAll(c); } public void clear(){ CHECKLOCK(); list.clear(); } @覆盖 public boolean equals(Object o){ return list.equals(o); } @覆盖 public int hashCode(){ return list.hashCode(); } public E get(int index){ return list.get(index); } public E set(int index,E element){ CHECKLOCK(); return list.set(index,element); } public void add(int index,E element){ CHECKLOCK(); list.add(index,element); } public E remove(int index){ CHECKLOCK(); return list.remove(index); } public int indexOf(Object o){ return list.indexOf(o); } public int lastIndexOf(Object o){ return list.lastIndexOf(o); } public ListIterator listIterator(){ return new LockableListListIterator(list.listIterator()); } public ListIterator listIterator(int index){ return new LockableListListIterator(list.listIterator(index)); } public List subList(int fromIndex,int toIndex){ 返回新的LockableListSubList(list.subList(fromIndex,toIndex)); } }
只需像这样使用它:
List list = new LockableList(new ArrayList(...)); list.setLocked(真); for(E e:list.iterator()) {...} list.setLocked(假);
希望它可以帮助别人。
如果您需要从列表中删除一些元素。 您可以维护另一个列表,例如要删除的元素。 最后调用removeAll(collection)。 当然这对大数据来说并不好。
由于不得不处理类似的问题,我编写了一个小助手来调试某些对象的并发访问情况(有时使用调试器会修改运行时行为以至于不会发生问题)。 这种方法类似于Francois所展示的方法,但更为通用。 也许它有助于某人: http : //code.google.com/p/kongcurrent/
在迭代它时修改动态列表时会收到ConcurrentModificationException(例如,在foreach循环中)。 您可能希望确保在任何地方都不这样做。