`
li2005
  • 浏览: 37752 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

遇到 ConcurrentModificationException,怎么办?

阅读更多
当线程用iterator的方法(iterator.next)循环一个collection的的时候,另外一个线程改变了这个collection,就会抛出ConcurrentModificationException。即使同步的collection类,比如 SnchronizedMap 或 SynchronizedList 也只是有条件的线程安全,这是因为所有单独的操作是线程安全的,但是依靠上别的操作结果的混合操作就可能出现线程问题。
Collection<String> myCollection = new ArrayList<String>(10);
myCollection.add("123");
myCollection.add("456");
myCollection.add("789");
for (Iterator it = myCollection.iterator(); it.hasNext();) {
String myObject = (String)it.next();
System.out.println(myObject);
if (someConditionIsTrue) {
myCollection.remove(myObject); //多线程时也会抛出 ConcurrentModificationException 
}
}


解决的方法:
(1)多线程的时候:
  1)你可以把你的 list 转换成数组用 list.toArray() 然后迭代这个数组,但当 list 很大的时候不推荐这样做。
  2)你可以用 synchronized 块把整个 list 操作和迭代全部包裹起来,不过当你的程序是高度并发的时候这个方法会对程序的伸缩性有影响。
  3)如果你用 JDK1.5 那么你可以用 ConcurrentHashMap 和 CopyOnWriteArrayList ,它们提供很好的伸缩性,用 ConcurrentHashMap.iterator() 迭代就不会抛出 ConcurrentModificationException。
(2)单线程的时候:

      it.remove();  //因为it有一个 myCollection 的引用,所以用 Iterator "it" 可以移除当前的对象,以可以用上面第3个方法。

别用
      myCollection.remove(myObject);  //避免在 Iterator迭代的时候,这会抛出ConcurrentModificationException的。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics