1月30日
java.util.ConcurrentModificationEx
1、
今天在写一个带缓存功能的访问代理程序时出现了java.util.ConcurrentModificationEx
源程序代码片段如下:caches为一个HashMap对象
解决办法为通过其相应的Iterator进行删除就可以了,修改后代码片段如下:
2、
撰写多线程代码时,你遇到过多少次下面的提示:
Exception in thread "main" java.util.ConcurrentModificationEx
这个异常产生的原因有几个。一是直接对集合调用删除操作而不是在枚举器上。二是不同的线程试图对集合进行增删操作的时候。
这个解决办法的第一步就是同步代码,使得你在枚举的时候其它的线程不能增删记录。但是如果每个枚举过程要进行复杂的计算或者是数据库访问的一部分的话,这个同步就会导致可怕的后果。为了减少负面影响,可以拷贝一个只读的枚举器,去掉同步,然后采用下列代码所示的方法:
重要的是记住,CopiedIterator不是一个克隆,只是一个只读的拷贝,所以它并没有保持原有的全部功能。最重要的是,不能再调用CopiedIterator.remove方法了。CopiedIterator.remove的实现如下:
枚举器的只读拷贝将用在同步状态上的时间减少到最小,因此可以增强全局的效率。
3、
当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行,
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationEx
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
有意思的是如果你的 Collection / Map 对象实际只有一个元素的时候, ConcurrentModificationEx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
------------------------------------------------------
try {
fis = new FileInputStream("d:/tongxun/info.txt");
ois = new ObjectInputStream(fis);
list = (ArrayList)ois.readObject();
System.out.println("请输入要删除的ID号:");
k=sb.nextInt();
for(Information ia:list)
if(ia.getId()==k){
n++;
list.remove(ia);}
l-=n;
ois.close();
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
问题补充:
现在就是不让我直接remove 应该怎么弄啊 愁
这个问题是说,你不能在对一个List进行遍历的时候将其中的元素删除掉 解决办法是,你可以先将要删除的元素用另一个list装起来,等遍历结束再remove掉 可以这样写 List delList = new ArrayList();//用来装需要删除的元素 for(Information ia:list) if(ia.getId()==k){ n++; delList.add(ia); } list.removeAll(delList);//遍历完成后执行删除