当我测试自己的答案以获取this问题的输出时,我得到了给定列表内容的以下输出:
// Add some strings into the list
list.add("Item 1");
list.add("Item 2");
list.add("Item 3");
list.add("Item 4");
输出:
Item 1
Item 2
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at com.akefirad.tests.Main$1.run(Main.java:34)
at java.lang.Thread.run(Thread.java:745)
但如果使用以下列表:
// Add some strings into the list
list.add("Item 1");
list.add("Item 2");
list.add("Item 3");
输出:
Item 1
Item 2
输出中没有例外,只会打印两个第一项。 谁能解释为什么它会像这样?感谢
注意:代码为here。
编辑:我的问题是为什么我没有打印第三个项目(意思是列表被修改),而且没有例外。
编辑代码以产生异常,请注意列表内容:
public class Main {
public static void main(String[] args) throws InterruptedException
{
final ArrayList<String> list = new ArrayList<String>();
list.add("Item 1");
list.add("Item 2");
list.add("Item 3");
list.add("Item 4");
Thread thread = new Thread(new Runnable()
{
@Override
public void run ()
{
for (String s : list)
{
System.out.println(s);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
});
thread.start();
Thread.sleep(2000);
list.remove(0);
}
}
答案 0 :(得分:4)
您尝试重现的行为与时间有很大关系。
当且仅当两个线程在修改列表时碰巧重叠时才会出现异常。
否则,你不会得到例外。
使用Thread.sleep()
无法可靠地强制两个线程之间的重叠,因为内核总是可以决定在它们唤醒后任意调度线程。
更新:OP想要知道是否必须发生以下两种情况之一:
Jon Skeet的答案指出了一个案例,其中打印的元素少于三个,没有例外,这意味着答案是否。
更一般地说,寻找ConcurrentModificationException
不是检测多个线程的可靠方法同时修改和读取对象。事实上,Exception的Javadoc非常具体地阐述了这一点。
请注意,通常情况下无法保证快速失败的行为 说话,在场的情况下不可能做出任何硬性保证 不同步的并发修改。失败快速操作投掷 ConcurrentModificationException是尽力而为的。因此,它 编写一个依赖于此异常的程序是错误的 它的正确性:应该只使用ConcurrentModificationException 检测错误。
答案 1 :(得分:2)
从根本上说,你在一个帖子中修改一个列表而在另一个帖子中迭代它,而你正在使用的列表实现不支持它。
ArrayList
迭代器实现似乎仅在next()
的调用中检测到对hasNext()
,而非的调用的无效修改。因此,如果您在<{em> remove()
调用之前进入循环的最后一次迭代,那么您将无法获得异常 - hasNext()
将返回false
}。另一方面,如果remove()
发生在最后一次调用next()
之前(并且如果在另一个线程上注意到 - 内存模型在这里发挥作用),那么你将得到例外。因此,例如,如果您将循环内睡眠更改为Thread.sleep(2500)
,那么您将在第二次迭代开始时获得异常,因为remove()
调用将在它之前发生。
如果要在多个线程中使用列表并且至少其中一个正在修改它,则应使用支持该列表的实现,例如CopyOnWriteArrayList
。