美文网首页
ArrayList 多线程报 数组越界异常

ArrayList 多线程报 数组越界异常

作者: 半支铅笔半块橡皮 | 来源:发表于2019-01-22 11:33 被阅读0次

    使用ArrayList在多线程环境可能会出现ArrayIndexOutOfBoundsException 异常,这篇文章就来看看为什么会出现这个错误。
    先看看下面的实例:

    public class ArrayListConcurrent {
    
        private static List<Integer> numberList = new ArrayList<>(100000);
    
        public static class AddToArrayList extends Thread{
            int startNum = 0;
    
            public AddToArrayList(int startNum){
                this.startNum = startNum;
            }
    
            @Override
            public void run() {
                int count = 0;
                while (count < 1000000){
                    numberList.add(startNum);
                    startNum += 2;
                    count++;
                }
            }
        }
    
        public static void main(String[] args) {
            Thread thread1 = new Thread(new AddToArrayList(0));
            Thread thread2 = new Thread(new AddToArrayList(1));
            thread1.start();
            thread2.start();
        }
    }
    

    在运行时报了如下的错误:

    Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 174718
        at java.util.ArrayList.add(ArrayList.java:412)
        at com.yumoon.concurrent.ArrayListConcurrent$AddToArrayList.run(ArrayListConcurrent.java:24)
        at java.lang.Thread.run(Thread.java:722)
    

    下面是几组测试数据:


    测试数据.png

    我们打开ArrayList的412这一行,看看源码:

    public boolean add(E e) {
      ensureCapacityInternal(size + 1);  // Increments modCount!!
      //这儿就是分行符,两个线程先后到达这儿,检查都发现不需要扩容,第一个线程在执行下面的步骤的时候没有问题,第二个就有数组越界了。
      elementData[size++] = e;      //这儿是412
      return true;
    }
    

    结合源码分析,看看ensureCapacityInternal 方法:

    //这个方法就是用来判断是否需要扩容的方法
    //结合前面的代码就是说只有有一个位置都可以
    private void ensureCapacityInternal(int minCapacity) {
            modCount++;
            // overflow-conscious code
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }
    

    比如 22 这儿报错就是因为 10 + 5 + (10+5)>> 1 = 22, (PS:需要熟悉ArrayList的扩容操作)
    总结:在多线程同时觉得不需要扩容,但是实际已经到了扩容的临界值的时候,就爆发了这个异常。

    相关文章

      网友评论

          本文标题:ArrayList 多线程报 数组越界异常

          本文链接:https://www.haomeiwen.com/subject/jwlljqtx.html