ConcurrentModificationException :如果不允许进行对象的并发修改,则检测到并发修改的方法可能会引发此异常。
上面是 javadoc 中的 ConcurrentModificationException 定义。
所以我尝试测试下面的代码:
final List<String> tickets = new ArrayList<String>(100000);
for (int i = 0; i < 100000; i++) {
tickets.add("ticket NO," + i);
}
for (int i = 0; i < 10; i++) {
Thread salethread = new Thread() {
public void run() {
while (tickets.size() > 0) {
tickets.remove(0);
System.out.println(Thread.currentThread().getId()+"Remove 0");
}
}
};
salethread.start();
}
代码很简单。
10 个线程从 arraylist 对象中删除元素。
可以肯定的是,多个线程访问一个对象。但运行正常。没有抛出异常。
为什么?
我引用了很大一部分内容ArrayListJavadoc 为您带来好处。解释您所看到的行为的相关部分会突出显示。
请注意,此实现不是同步的。如果是多线程
同时访问 ArrayList 实例,并且至少其中之一
线程从结构上修改列表,必须同步
外在地。 (结构修改是任何添加或
删除一个或多个元素,或显式调整后备数组的大小;
仅仅设置元素的值不是结构性的
修改。)这通常是通过同步某些
自然封装列表的对象。如果不存在这样的对象,
列表应该使用 Collections.synchronizedList “包装”
方法。最好在创建时完成此操作,以防止意外
对列表的不同步访问:
列表列表 = Collections.synchronizedList(new ArrayList(...));
此类的 iterator 和 listIterator 方法返回的迭代器
快速失败:如果列表在结构上随时被修改
迭代器以任何方式创建,除了通过迭代器自己的
删除或添加方法时,迭代器将抛出
并发修改异常。因此,面对并发
修改后,迭代器会快速而干净地失败,而不是
在不确定的时间冒任意、非确定性行为的风险
将来。
请注意,无法保证迭代器的快速失败行为
因为一般来说,不可能做出任何硬性保证
存在不同步并发修改的情况。快速失败
迭代器尽力抛出 ConcurrentModificationException
基础。因此,编写依赖于
关于此异常的正确性:快速失败行为
迭代器应该仅用于检测错误。
如果从结构上修改列表,ArrayLists 通常会抛出并发修改异常通过迭代器访问它时(但即使这也不是绝对的保证)。请注意,在您的示例中,您直接从列表中删除元素,并且没有使用迭代器。
如果您感兴趣,您还可以浏览以下实现ArrayList.remove,以便更好地了解其工作原理。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)