• ArrayList的ConcurrentModificationException异常和多线程下的异常


    一、ConcurrentModificationException

    ArrayList源码看为什么出现异常:

    public class ArrayList<e> extends AbstractList<e>
            implements Cloneable, Serializable, RandomAccess {
             
             
             @Override public boolean remove(Object object) {
            Object[] a = array;
            int s = size;
            if (object != null) {
                for (int i = 0; i < s; i++) {
                    if (object.equals(a[i])) {
                        System.arraycopy(a, i + 1, a, i, --s - i);
                        a[s] = null;  // Prevent memory leak
                        size = s;
                        modCount++;  // 只要删除成功都是累加
                        return true;
                    }
                }
            } else {
                for (int i = 0; i < s; i++) {
                    if (a[i] == null) {
                        System.arraycopy(a, i + 1, a, i, --s - i);
                        a[s] = null;  // Prevent memory leak
                        size = s;
                        modCount++;  // 只要删除成功都是累加
                        return true;
                    }
                }
            }
            return false;
        }   
     
     
        @Override public Iterator<e> iterator() {
            return new ArrayListIterator();
        }   
             
        private class ArrayListIterator implements Iterator<e> {
              ......
        
              // 全局修改总数保存到当前类中
            /** The expected modCount value */
            private int expectedModCount = modCount;
     
            @SuppressWarnings("unchecked") public E next() {
                ArrayList<e> ourList = ArrayList.this;
                int rem = remaining;
                   // 如果创建时的值不相同,抛出异常,
                if (ourList.modCount != expectedModCount) {
                    throw new ConcurrentModificationException();
                }
                if (rem == 0) {
                    throw new NoSuchElementException();
                }
                remaining = rem - 1;
                return (E) ourList.array[removalIndex = ourList.size - rem];
            }   
             
              ......
         }
    }

      由上可知,如果遍历中作get,remove操作都会改变modCount的值,但是此时expectedModCount还是保存以前的modCount的值,肯定不相等,抛出异常。

    二、多线程下的异常

    1、发生 ArrayIndexOutOfBoundsException 异常;

      问题是出现在多线程并发访问下,由于没有同步锁的保护,造成了 ArrayList 扩容不一致的问题。

    2、程序正常运行,输出了少于实际容量的大小;

      这个也是多线程并发赋值时,对同一个数组索引位置进行了赋值,所以出现少于预期大小的情况。

    3、程序正常运行,输出了预期容量的大小;

      这是正常运行结果,未发生多线程安全问题,但这是不确定性的,不是每次都会达到正常预期的。

    三、线程安全的CopyOnWriteArrayList

    Java并发集合(一)-CopyOnWriteArrayList分析与使用

  • 相关阅读:
    ubuntu重复登录问题
    CUDA相关问题
    pytorch安装(使用pip3装到conda环境下)
    ubuntu16.04 anaconda的安装和卸载
    vscode插件安装失败的解决方案
    使用ffmpeg进行视频截图
    Spring加载早期获取BasePackage
    chrome最耐看的主题
    针对MySQL的MVCC多版本并发控制的一些总结
    docker创建mysql容器,并挂载数据+配置
  • 原文地址:https://www.cnblogs.com/java-zzl/p/10472043.html
Copyright © 2020-2023  润新知