猿问

ArrayList#上的ArrayIndexOutOfBounds包含(多线程)

最近,我遇到了导致ArrayIndexOutOfBoundsExceptionon的意外错误(不是我的代码)ArrayList#contains。此处的相关代码如下。


private static final List<String> list = new ArrayList<>();


static void register() {

    update();

    new Timer().schedule(new TimerTask() {

        @Override

        public void run() {

            update();

        }

    }, 0, 21600000);

}


private static void update() {

    list.clear();

    new Thread(() -> {

        List<String> other; //should always be the same length.

        list.addAll(other);

    }).start();

}


public static boolean contains(String string) { //called long after register

    return list.contains(string); //throws ArrayIndexOutOfBounds

}

我很清楚这ArrayList不是线程安全的,可以使用来修复它Collections#synchronizedList。我的问题是了解此特定代码如何引发ArrayIndexOutOfBoundsException。


异常的stacktrace标识中的以下代码ArrayList#indexOf。


for (int i = 0; i < size; i++)

    if (o.equals(elementData[i])) //here

        return i;

在我看来,这只有在size大于时才会发生elementData.length。据我了解,ArrayList#clear实际上并没有减少支持数组的长度。到的调用addAll仅应增加其容量,并且size在扩展数组之后始终会对其进行更新。我看不到在size大于阵列容量的状态下怎么回事。


我注意到的一个特定细节是上的延迟Timer为0,这意味着update()快速连续调用了两次。我最好的猜测是,addAll调用在某种程度上是重叠的,这使列表成为某种混合的无效状态。


如果有人可以解释这里发生的事情,那就太好了!


斯蒂芬大帝
浏览 348回答 1
1回答
随时随地看视频慕课网APP

相关分类

Java
我要回答