其他几天我们在这段代码中的应用程序日志中发现了一个相当尴尬的例外:
final LIST currentSinks = this.sinks;
if (null != currentSinks && !currentSinks.isEmpty())
{
for (final DataSink<? super T> sink : currentSinks)// **the exception is thrown here**
{
sink.updated(oldValue, newValue);
}
}
LIST 是
public abstract class AbstractDataSource<T, LIST extends Collection<DataSink<? super T>>>
使用的实现是ArrayList。它只是抛出NoSuchElementException。说实话,我真的不明白为什么。无论我尝试了什么,都只有预期的行为:没有迭代通过for。
堆栈跟踪的第一行:
java.util.NoSuchElementException在这里捕获:java.util.ArrayList $ Itr.next(ArrayList.java:834)
任何提示或解释都将受到高度赞赏。
修改 可能一个好的起点是隔离UT中的行为。有什么想法吗?
答案 0 :(得分:1)
好吧,我将努力总结评论中讨论的内容。谢谢大家,并随意编辑这个答案。
错误描述感觉就像并发错误,因此我们的理论是:
可能是另一个线程在Iterator的
hasNext()
和next()
调用之间移除了一个元素,这个元素发生在for(:)
循环的幕后(感谢Steve!)。
所以,让我们测试一下我们的理论:
1)首先,list
类型为ArrayList
,我们提供的是ArrayList文档:
ArrayList未同步,因此如果您需要多线程访问,请考虑使用
List l = Collections.synchronizedList(new ArrayList(...));
2)然后我们检查源代码以查找对NoSuchElementException
的引用:java.util.ArrayList.java
上没有发现,但java.util.AbstractList.java
中有五次出现,最有趣的是:
// under: public ListIterator<E> listIterator(final int index) {
// return new ListIterator<E>() {
// line 1040:
/**
* Retrieves the next object from the list.
*
* @return The next object.
* @throws NoSuchElementException if there are no
* more objects to retrieve.
* @throws ConcurrentModificationException if the
* list has been modified elsewhere.
*/
public E next()
{
if (position == size)
throw new NoSuchElementException();
position++;
return i.next();
}
回到我们的理论,我们可以说:
ArrayList
未同步(1),并且在任何并发修改检查(2)之前,NoSuchElementException
会抛出iterator.next()
。希望它可以帮助您解决问题!