Java ArrayList.Itr#next()何时会在此行抛出ConcurrentModificationException?
这个问题是关于JDK1.8.0_74的。该类是Java ArrayList.Itr#next()何时会在此行抛出ConcurrentModificationException?,java,arraylist,iterator,Java,Arraylist,Iterator,这个问题是关于JDK1.8.0_74的。该类是java.util.ArrayList$Itr。调用ArrayList\iterator()方法时,将返回此(内部)类的实例。具体来说,我的问题是关于Itr上的next()方法: 850 public E next() { 851 checkForComodification(); 852 int i = cursor; 853 if (i >= size) 854
java.util.ArrayList$Itr
。调用ArrayList\iterator()
方法时,将返回此(内部)类的实例。具体来说,我的问题是关于Itr
上的next()
方法:
850 public E next() {
851 checkForComodification();
852 int i = cursor;
853 if (i >= size)
854 throw new NoSuchElementException();
855 Object[] elementData = ArrayList.this.elementData;
856 if (i >= elementData.length)
857 throw new ConcurrentModificationException();
858 cursor = i + 1;
859 return (E) elementData[lastRet = i];
860 }
我理解checkForComodification
call on line#851的基本原理[1]。我也理解第853行的(I>=size)
检查[2]
但是,检查如果(i>=elementData.length)
在线#856在防范什么情况呢?
在单线程代码中,我无法使用在线的ConcurrentModificationException
使某些代码失败
[1] :迭代器创建失败后的结构修改:
static void coMod() {
ArrayList<Integer> list = new ArrayList<>(4);
list.add(1);
list.add(2);
Iterator<Integer> itr = list.iterator();
list.remove(0); //structural modification after iterator creation
if (itr.hasNext()) {
System.out.println("wait, there's more!");
itr.next(); // modification while iterating --
// fails at java.util.ArrayList$Itr.next(ArrayList.java:851)
}
}
static void coMod(){
ArrayList=新的ArrayList(4);
增加第(1)款;
增加(2);
迭代器itr=list.Iterator();
list.remove(0);//迭代器创建后的结构修改
if(itr.hasNext()){
System.out.println(“等等,还有更多!”;
itr.next();//迭代时的修改--
//在java.util.ArrayList$Itr.next处失败(ArrayList.java:851)
}
}
[2] :迭代器到达末尾后失败
static void noHasNext() {
ArrayList<Integer> list = new ArrayList<>(4);
Iterator<Integer> itr = list.iterator();
itr.next(); // unguarded next call --
// fails at java.util.ArrayList$Itr.next(ArrayList.java:854)
}
static void noHasNext(){
ArrayList=新的ArrayList(4);
迭代器itr=list.Iterator();
itr.next();//未防护的下一个调用--
//在java.util.ArrayList$Itr.next处失败(ArrayList.java:854)
}
这是只有在多线程情况下才会发生的情况
我相信线程1必须在执行第855行之前立即停止。线程2将出现并将ArrayList.this.elementData设置为一个新的(较小的)数组
与ArrayIndexOutOfBoundsException异常相比,提供更好的异常是一种廉价的检查,否则会抛出该异常。从理论上讲,优化器甚至可能检测到正在显式检查的数组边界,而忽略对ArrayIndexOutOfBoundsException的检查。这是仅在多线程情况下才会发生的情况 我相信线程1必须在执行第855行之前立即停止。线程2将出现并将ArrayList.this.elementData设置为一个新的(较小的)数组
与ArrayIndexOutOfBoundsException异常相比,提供更好的异常是一种廉价的检查,否则会抛出该异常。理论上,优化器甚至可能检测到正在显式检查的数组边界,而忽略对ArrayIndexOutOfBoundsException的检查。“在单线程代码中”-这可能是这里的重要因素…我明白了,但是
ArrayList
不是线程安全的;那么它需要进行检查吗?这只是一个调试道具-事实上,它甚至在这里的Javadoc简介中提到:如果元素数组通过从另一个线程添加而增长,size
的新值会传播到调用next
的线程,但该线程仍会看到ArrayList的旧值。这个.elementData
。。。?听起来有些牵强,但这是我能想到的最好的方法。“在单线程代码中”-这可能是这里的重要因素…我明白了,但是ArrayList
不是线程安全的;那么它需要进行检查吗?这只是一个调试道具-事实上,它甚至在这里的Javadoc简介中提到:如果元素数组通过从另一个线程添加而增长,size
的新值会传播到调用next
的线程,但该线程仍会看到ArrayList的旧值。这个.elementData
。。。?对我来说,这听起来有些牵强,但这是我能想到的最好的办法。这并不是说“这是一种只能在多线程情况下发生的事情”。@LewBloch解释了它是如何在单线程情况下发生的。问题是在第857行(而不是一般情况下)抛出异常的具体时间。checkForComodification()是对修改的常规(单线程)检查。并非“这是仅在多线程情况下才会发生的事情”。@LewBloch解释了它如何在单线程情况下发生。问题是在第857行(而不是一般情况下)抛出异常的具体时间。checkForComodification()是修改的常规(单线程)检查。