(转)ConcurrentModificationException 问题
程序员文章站
2022-05-21 18:36:03
...
原文地址:http://www.cnblogs.com/sunwufan/archive/2012/05/21/2511747.html
当考虑到列表中需要修改的元素很多时,可以考虑上一篇博文:
通过CopyOnWriteArrayList,在遍历过程中,对list元素进行删除和添加操作
方法一(效率不高):
这个问题是说,你不能在对一个List进行遍历的时候将其中的元素删除掉 解决办法是,你可以先将要删除的元素用另一个list装起来,等遍历结束再remove掉 可以这样写
List delList = new ArrayList();//用来装需要删除的元素
for(Information ia:list)
if(ia.getId()==k){
n++;
delList.add(ia);
}
list.removeAll(delList);//遍历完成后执行删除
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
方法二:同步操作list时,一边迭代remove,一边新增.那么会报错 java.util.ConcurrentModificationException
查看api发现vector有个好方法可以解决这个错误.
首先是用arraylist
// private Vector list;//两种list方式
private List list;
public void init(){
// list = new Vector();
list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
}
public void removeIt(){//iterator
Iterator it = list.iterator();
for(int i=0;it.hasNext();i++){
String a = (String)it.next();
System.out.println(a);
if(a.equals("c")){
//list.remove(a);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
it.remove();
System.out.println("remove c");
}
}
}
// public void removeEm(){//enumeration
// Enumeration e = list.elements();
// for(int i=0;e.hasMoreElements();i++){
// String a = (String)e.nextElement();
// System.out.println(a);
// if(a.equals("c")){
// try {
// Thread.sleep(1000);
// } catch (InterruptedException ee) {
// }
// list.remove(a);
// System.out.println("remove c");
// }
// }
// }
public void add(){//先用迭代,再添加
try {
Thread.sleep(500);
} catch (Exception e) {
// TODO: handle exception
}
list.add("c");
System.out.println("add c");
}
public void run() {
removeIt();
// removeEm();
}
public static void main(String[] args) {
TestConcurrentModificationException t = new TestConcurrentModificationException();
t.init();
t.start();
t.add();
}
运行结果:
a
b
c
add c
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.remove(Unknown Source)
at test.TestConcurrentModificationException.removeIt(TestConcurrentModificationException.java:33)
at test.TestConcurrentModificationException.run(TestConcurrentModificationException.java:69)
其次是vector
private Vector list;//两种list方式
// private List list;
public void init(){
list = new Vector();
// list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
}
public void removeIt(){//iterator
Iterator it = list.iterator();
for(int i=0;it.hasNext();i++){
String a = (String)it.next();
System.out.println(a);
if(a.equals("c")){
//list.remove(a);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
it.remove();
System.out.println("remove c");
}
}
}
public void removeEm(){//enumeration
Enumeration e = list.elements();
for(int i=0;e.hasMoreElements();i++){
String a = (String)e.nextElement();
System.out.println(a);
if(a.equals("c")){
try {
Thread.sleep(1000);
} catch (InterruptedException ee) {
}
list.remove(a);
System.out.println("remove c");
}
}
}
public void add(){//先用迭代,再添加
try {
Thread.sleep(500);
} catch (Exception e) {
// TODO: handle exception
}
list.add("c");
System.out.println("add c");
}
public void run() {
// removeIt();
removeEm();
}
public static void main(String[] args) {
TestConcurrentModificationException t = new TestConcurrentModificationException();
t.init();
t.start();
t.add();
}
运行结果:
a
b
c
add c
remove c
e
f
c
remove c
api上说,
由 Vector 的 iterator 和 listIterator 方法所返回的迭代器是快速失败的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代 器自身的 remove 或 add 方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生 不确定行为的风险。Vector 的 elements 方法返回的 Enumeration 不是 快速失败的。
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测 bug。
当然如果使用其他的集合,那就没有什么好办法了.只有存放起来,每次取一个list对象,并不是实时.
当考虑到列表中需要修改的元素很多时,可以考虑上一篇博文:
通过CopyOnWriteArrayList,在遍历过程中,对list元素进行删除和添加操作
方法一(效率不高):
这个问题是说,你不能在对一个List进行遍历的时候将其中的元素删除掉 解决办法是,你可以先将要删除的元素用另一个list装起来,等遍历结束再remove掉 可以这样写
List delList = new ArrayList();//用来装需要删除的元素
for(Information ia:list)
if(ia.getId()==k){
n++;
delList.add(ia);
}
list.removeAll(delList);//遍历完成后执行删除
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
方法二:同步操作list时,一边迭代remove,一边新增.那么会报错 java.util.ConcurrentModificationException
查看api发现vector有个好方法可以解决这个错误.
首先是用arraylist
// private Vector list;//两种list方式
private List list;
public void init(){
// list = new Vector();
list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
}
public void removeIt(){//iterator
Iterator it = list.iterator();
for(int i=0;it.hasNext();i++){
String a = (String)it.next();
System.out.println(a);
if(a.equals("c")){
//list.remove(a);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
it.remove();
System.out.println("remove c");
}
}
}
// public void removeEm(){//enumeration
// Enumeration e = list.elements();
// for(int i=0;e.hasMoreElements();i++){
// String a = (String)e.nextElement();
// System.out.println(a);
// if(a.equals("c")){
// try {
// Thread.sleep(1000);
// } catch (InterruptedException ee) {
// }
// list.remove(a);
// System.out.println("remove c");
// }
// }
// }
public void add(){//先用迭代,再添加
try {
Thread.sleep(500);
} catch (Exception e) {
// TODO: handle exception
}
list.add("c");
System.out.println("add c");
}
public void run() {
removeIt();
// removeEm();
}
public static void main(String[] args) {
TestConcurrentModificationException t = new TestConcurrentModificationException();
t.init();
t.start();
t.add();
}
运行结果:
a
b
c
add c
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.remove(Unknown Source)
at test.TestConcurrentModificationException.removeIt(TestConcurrentModificationException.java:33)
at test.TestConcurrentModificationException.run(TestConcurrentModificationException.java:69)
其次是vector
private Vector list;//两种list方式
// private List list;
public void init(){
list = new Vector();
// list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
}
public void removeIt(){//iterator
Iterator it = list.iterator();
for(int i=0;it.hasNext();i++){
String a = (String)it.next();
System.out.println(a);
if(a.equals("c")){
//list.remove(a);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
it.remove();
System.out.println("remove c");
}
}
}
public void removeEm(){//enumeration
Enumeration e = list.elements();
for(int i=0;e.hasMoreElements();i++){
String a = (String)e.nextElement();
System.out.println(a);
if(a.equals("c")){
try {
Thread.sleep(1000);
} catch (InterruptedException ee) {
}
list.remove(a);
System.out.println("remove c");
}
}
}
public void add(){//先用迭代,再添加
try {
Thread.sleep(500);
} catch (Exception e) {
// TODO: handle exception
}
list.add("c");
System.out.println("add c");
}
public void run() {
// removeIt();
removeEm();
}
public static void main(String[] args) {
TestConcurrentModificationException t = new TestConcurrentModificationException();
t.init();
t.start();
t.add();
}
运行结果:
a
b
c
add c
remove c
e
f
c
remove c
api上说,
由 Vector 的 iterator 和 listIterator 方法所返回的迭代器是快速失败的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代 器自身的 remove 或 add 方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生 不确定行为的风险。Vector 的 elements 方法返回的 Enumeration 不是 快速失败的。
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测 bug。
当然如果使用其他的集合,那就没有什么好办法了.只有存放起来,每次取一个list对象,并不是实时.
上一篇: 关于php处理xml的一个小疑点
下一篇: Java中的随机类Random