• 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分析与使用

  • 相关阅读:
    我的JAVA之旅(二)初识JAVA
    ORACLE并发处理
    我的JAVA之旅(一)安装配置
    我的JAVA之旅(三) 元素语法
    改变一生的五句话
    InstallShield集成安装MSDE2000最小版本(三) fishout特许授权发布
    IS2009修改XML File 奕婷特许授权发布
    SQL Server中多个表格求出相同列和不同列(答案来自CSDN上SQL专家的回答)
    InstallShield集成安装MSDE2000最小版本(二) fishout特许授权发布
    Installshield停止操作系统进程的代码 IS6及以上版本适用
  • 原文地址:https://www.cnblogs.com/java-zzl/p/10472043.html
Copyright © 2020-2023  润新知