精华内容
下载资源
问答
  • Java并发修改异常

    千次阅读 2017-11-28 17:10:44
    今天突然有人问我并发修改异常怎么回事,当时只记得解决方案,不是很详细的知道底层原因,花了一点点时间,看了下源码,发现其实很简单。以下是我的见解 在Java开发中Exception in thread "main" java....
     

    今天突然有人问我并发修改异常怎么回事,当时只记得解决方案,不是很详细的知道底层原因,花了一点点时间,看了下源码,发现其实很简单。以下是我的见解

    在Java开发中Exception in thread "main" java.util.ConcurrentModificationException, 这是一个并发修改异常,主要原因是迭代器遍历元素的时候,通过集合是不能修改元素的

     

    假设我们要实现这样一个例子: 判断集合里面有没有"world"这个元素,如果有,就添加一个"javaee"元素

    出现异常的代码如下:

    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class Test {
    
        public static void main(String[] args) {
            ArrayList<String> array = new ArrayList<String>();
    
            // 创建并添加元素
            array.add("hello");
            array.add("world");
            array.add("java");
            Iterator it = array.iterator();
            while (it.hasNext()) {
                String s = (String) it.next();
                if ("world".equals(s)) {
                    array.add("javaee");
                }
            }
        }
    }

    1.异常解释

    • ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
    • 产生的原因:
         迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。
         简单描述就是:迭代器遍历元素的时候,通过集合是不能修改元素的。
    • 如何解决呢?
         A:迭代器迭代元素,迭代器修改元素
         B:集合遍历元素,集合修改元素(普通for)

    2.下面用两种方法去解决这个异常

    import java.util.ArrayList;
    
    public class Test {
    
        public static void main(String[] args) {
            ArrayList<String> array = new ArrayList<String>();
    
            // 创建并添加元素
            array.add("hello");
            array.add("world");
            array.add("java");
            // 方式1:迭代器迭代元素,迭代器修改元素
            // 而Iterator迭代器却没有添加功能,所以我们使用其子接口ListIterator
            // ListIterator lit = array.listIterator();
            // while (lit.hasNext()) {
            // String s = (String) lit.next();
            // if ("world".equals(s)) {
            // lit.add("javaee");
            // }
            // }
            // System.out.println("list1:" + array);
            // 方式2:集合遍历元素,集合修改元素(普通for)
             for (int x = 0; x < array.size(); x++) {
             String s = (String) array.get(x);
             if ("world".equals(s)) {
             array.add("javaee");
             }
             }
    
             System.out.println("list2:" + array);
    
            // 方式3:增强for循环
            // 增强for循环写的话会报同样的错误,因为它本身就是用来替代迭代器的
            // for (String s : array) {
            // if ("world".equals(s)) {
            // array.add("javaee");
            // }
            // }
            // System.out.println("list3:" + array);
        }
    }
    
    
    提示:集合有个属性modCount,每当对集合修改一次,modCount的值就会自增,,迭代器在遍历的时候,底层会new一个Itr的内部类,初始化了一个变量记录了集合的modCount值,
    此变量名是expectedModCount。迭代器在调用next()方法时候会去比较这两个值是否相等,不相等则抛出异常
     
    final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }

     

    https://blog.csdn.net/qq_29534705/article/details/80899351

    展开全文
  • 并发修改异常一 什么是并发修改异常(ConcurrentModificationException)二并发修改异常(ConcurrentModificationException)产生的原因1 modCount是什么意思?2 expectedModCount是什么意思?3 modCount != ...

    一 什么是并发修改异常(ConcurrentModificationException)

    当我们对集合进行迭代(遍历)的时候,同时(并发)对集合进行修改,就会产生并发修改
    比如说遍历一个集合时,同时对其中一个元素删除,修改等等操作。
    或者 list 在多线程情况下 既有读又有写,报出ConcurrentModificationException问题,
    概括来说分为两种情况
    1一边遍历集合,而另一边在修改集合时,会报ConcurrentModificationException错误
    2在多线程进行插入操作时,由于没有进行同步操作,容易丢失数据,因此会报ConcurrentModificationException错误。
    代码案例(来源于尚硅谷)

    public class LThread {
        public static void main(String[] args) {
           List list=new ArrayList();//创建数组
            for ( int i = 0; i < 30; i++) {
                int x=i;
                new Thread(()->{
                    list.add(UUID.randomUUID().toString().substring(0,8));//往数组里面放数据
                    System.out.println(list);
                }).start();
            }
        }
    }
    

    在这里插入图片描述

    二并发修改异常(ConcurrentModificationException)产生的原因

    点进报错提示
    在这里插入图片描述
    **发现是 modCount != expectedModCount,返回ConcurrentModificationException **

    1 modCount是什么意思?

    The number of times this list has been structurally modified. Structural modifications are those that change the size of the list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results
    这个数是结构化修改的次数,结构修改是指改变列表的大小,或者以一种可能产生错误结果的方式扰乱列表。

    2 expectedModCount是什么意思?

    在这里插入图片描述
    期望的修改次数

    3 modCount != expectedModCount的原因

    分析源码
    在这里插入图片描述
    在这里插入图片描述

    显而易见 当添加add或删除元素remove来修改集合,那么modCount将更改,赋值给expectedModCount。
    当多线程时,有的线程没写进去集合的size(大小)没变,有的线程写进去集合的size(大小)变了,导致计数器modCount的值发生了改变并不是有序+1,但是往出输出时,导致了expectedModCount与modCount两个计数器不相同,于是返回ConcurrentModificationE错误。

    在这里插入图片描述
    在这里插入图片描述
    和预期的结果 差别十分大,有的线程刚改变完modCount,而另一个线程要输出改变前后的modCount。

    三解决并发修改异常的方案

    1使用 Vector(同步的)

    在这里插入图片描述

    为什么使用Vector

    Vector是线程安全的容器可以替换ArrayList,只不过有点古老。也可以理解为每一个操作都加有synchronized,但是严重影响效率。

    在这里插入图片描述

    每个线程使用Add时,都会添加synchronize 其他线程无法在调用add方法,解决并发修改的问题

    2 使用Collections.synchronizedList

    Collections.synchronizedList 的实现原理

    在这里插入图片描述

    为什么使用Collections.synchronizedList

    返回指定列表支持的同步(线程安全)列表. 在 List的操作加了一层 synchronize 同步控制,但是对于 使用 Iterator 遍历列表时,Collections.synchronizedList 可能发生ConcurrentModificationE。
    在这里插入图片描述

    3 使用 CopyOnWriteArrayList (读写分离的思想)

    为什么使用 CopyOnWriteArrayList

    源码分析 add、rome元素时,上锁保证同一时刻最多只有一个线程向list中添加元素,肯定是线程安全的, 同时add、rome都是不会去修改
    原数组的,所以modCount 是不会去被其他线程改变的。

    在这里插入图片描述

    4 CopyOnWriteArrayList 在数组的迭代时也可防止并发修改异常

    public class ModificationException {
        public static void main(String[] args) {
            List<String> list =new ArrayList();
            list.add("m");
            list.add("y");
            list.add("t");  //Arraylist 经常见的需求 迭代 找到一个数然后去掉
            for (String str : list) {
                if ("t".equals(str)) {
                    list.remove("t"); //两个计数器不相同 报错误
                }
                System.out.println(list);
            }
        }
    }
    

    在这里插入图片描述
    使用 CopyOnWriteArrayList
    在这里插入图片描述

    展开全文
  • Java并发修改异常的源码解析

    千次阅读 多人点赞 2018-07-03 15:31:01
    Java并发修改异常的源码解析 1. 什么时候会产生并发修改异常 并发的意思是同时发生,那么其实并发修改的字面意思就是同时修改,通过查看JDK的API我们可以得知,并发修改异常的出现的原因是:当方法检测到对象的...

    Java并发修改异常的源码解析

    1. 什么时候会产生并发修改异常

    • 并发的意思是同时发生,那么其实并发修改的字面意思就是同时修改,通过查看JDK的API我们可以得知,并发修改异常的出现的原因是:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
    • 一个常见的场景就是:当我们在对集合进行迭代操作的时候,如果同时对集合对象中的元素进行某些操作,则容易导致并发修改异常的产生。

      • 例如我们要完成以下需求:
        • 在一个存储字符串的集合中,如果存在字符串”Java”,则添加一个”Android”
        • 示范代码如下:
      public class Test {
          public static void main(String[] args){
              ArrayList<String> list = new ArrayList<String>();
              list.add("Java");
              list.add("Hello");
              list.add("World");
              Iterator<String> it = list.iterator();//获取迭代器对象
              while(it.hasNext()){ //如果迭代器判断集合中还有下一个元素则继续循环
                  String str = it.next();//获取集合中迭代器所指向的元素
                  if(str.equals("Java")) {//如果这个元素内容是"Java"
                      list.add("Android");//则在集合中添加一个"Android"
                  }
              }
          }
      }
      
      • 控制台输出:
      Exception in thread "main" java.util.ConcurrentModificationException
          at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
          at java.util.ArrayList$Itr.next(ArrayList.java:831)
          at com.itheima.day02.Test5.main(Test5.java:17)
      
    • 控制台显示的ConcurrentModificationException,即并发修改异常
    • 下面我们就以ArrayList集合中出现的并发修改异常为例来分析异常产生的原因。

    2. 异常是如何产生的

    • 2.1 想要知道异常出现的原因,我们需要找到源码中异常出现的根源

      • 我们能通过控制台找到异常的根源:
        • at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
        • 异常出现的位置出现在ArrayList类中内部类Itr中的checkForComodification方法
      • 贴出此方法的源码:

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
        
      • 由此方法可知,当一个名为modCount的变量值不等于expectedModCount的变量值时,异常对象被抛出。

    • 2.2 继续探究这两个变量分别是代表什么

      • modCount

        • modCount是定义在AbstractList抽象类中的public修饰的成员变量,而ArrayList是此类的子类,那么代表ArrayList继承到了modCount这个变量。
        • 源码中对modCount的解释是:

          The number of times this list has been structurally modified

          • 我们可以理解为:这个变量其实就代表了集合在结构上修改的次数

      • expectedModCount

        • expectedModCount是内部类Itr中的成员变量,当ArrayList对象调用iteroter()方法时,会创建内部类Itr的对象,并给其成员变量expectedModCount赋值为ArrayList对象成员变量的值modCount。

          以下是内部类Itr的部分源码,我们主要看此内部类成员变量部分

          private class Itr implements Iterator<E> {
              int cursor;      
              int lastRet = -1; 
              int expectedModCount = modCount;
              ....
          }
          
          • 由此段代码可知,当Itr对象被创建的时候,expectedModCount的值会等于modCount变量的值。

      • 那么modCount变量在赋值给expectedModCount之前又会如何变化呢?

        • 当我们创建ArrayList对象的时候,ArrayList对象里包含了此变量modCount并且初始化值为0;
        • 通过查看源码,我们能发现在ArrayList类中有操作modCount的方法都是添加元素的相关功能和删除元素的相关功能。例如:

          • 每删除一个元素,modCount的值会自增一次
          public E remove(int index) {
              rangeCheck(index);
              modCount++;
              ...//此处省略代码
              E oldValue = elementData(index);
              return oldValue;
          }
          
          • 在add方法中会调用下面的方法,意味着每添加一个元素,modCount的值也会自增一次
          private void ensureExplicitCapacity(int minCapacity) {
                  modCount++;
                  if (minCapacity - elementData.length > 0)
                      grow(minCapacity);
          }
          
        • 也就是说:我们每次进行对集合中的元素个数变化的操作时,modCount的值就会+1
          • 但是这个操作仅限于增删元素,修改元素值并不会影响modCount的值
        • 再结合API中对此变量的解释,我们可以得出大致的判断:
          • 其实modCount变量就是记录了对集合元素个数的改变次数

    • 2.3 分析完这两个关键的变量,我们再结合迭代器的工作流程来分析异常出现的过程

      • 2.3.1 迭代器的创建

        • 上文中已经提到过,当ArrayList对象调用iteroter()方法时,会创建内部类Itr的对象。
        • 此时迭代器对象中有两个最关键的成员变量:cursor、expectedModCount

          private class Itr implements Iterator<E> {
              int cursor;       // index of next element to return
              int lastRet = -1; // index of last element returned; -1 if no such
              int expectedModCount = modCount;
              .....//此处省略下方其他源码
          }
          
        • cursor
          • 迭代器的工作就是将集合中的元素逐个取出,而cursor就是迭代器中用于指向集合中某个元素的指针
          • 在迭代器迭代的过程中,cursor初始值为0,每次取出一个元素,cursor值会+1,以便下一次能指向下一个元素,直到cursor值等于集合的长度为止,从而达到取出所有元素的效果。
        • expectedModCount
          • expectedModCount在迭代器对象创建时被赋值为modCount
          • 上文已经分析过,modCount应该理解为集合元素个数的改变次数,或者说结构修改次数
          • 也就是说,当创建完迭代器对象后,如果我们没有对集合结构进行修改,expectedModCount的值是会等于modCount的值的。
          • 在迭代集合元素的过程中,迭代器通过检查expectedModCount和modCount的值是否相同,以防止出现并发修改。

      • 2.3.2 迭代器迭代过程源码分析:

        • 在2.3.1中我们已经简要的分析过了迭代器工作中最重要的两个变量,下面贴出更多源码结合上文的分析继续说明迭代器是如何工作的。

          • 我们在使用迭代器的时候,一般会调用迭代器的hasNext()方法判断是否还有下一个元素,此方法源码非常简单:

            public boolean hasNext() {
                return cursor != size;
            }
            

            分析:

            • cursor初始值是0,默认指向集合中第一个元素,每次取出一个元素,cursor值就会自增一次
            • size是集合中的成员变量,用于表示集合的元素个数
            • 因为集合中最后一个元素的索引为size-1,只要cursor值不等于size那么就证明还有下一个元素,此时hasNext方法返回true,如若cursor值与size相等了,那么证明已经迭代完了最后一个元素,此方法返回false。

          • 当我们通过迭代器的hasNext方法返回true值确信集合中还有元素的时候,通常我们会通过迭代器的另一个方法next取出此元素。源码如下:

            public E next() {
                checkForComodification();
                int i = cursor;
                if (i >= size)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i + 1;
                return (E) elementData[lastRet = i];
            }
            
            //在next方法的第一行调用了此方法
            final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
            

            分析:

            • next()方法第一行就是调用checkForComodification()方法,也就是我们上文中分析过并发修改异常出现根源
            • 当迭代器通过next()方法返回元素之前都会检查集合中的modCount和最初赋值给迭代器的expectedModCount是否相等,如果不等,则抛出并发修改异常。
            • 也就说,当迭代器工作的过程中,不允许集合擅自修改集合结构,如果修改了会导致modCount值变化,从而不会等于expectedModCount,那么迭代器就会抛出并发修改异常。
            • 如果没有异常产生,next()方法最后一行会返回cursor指向的元素。

    3. 并发修改异常的意义及异常解决方案

    • 3.1 在上文中我们已经结合源码仔细的分析了并发修改异常产生的原因以及过程,那么这个异常的产生对程序而言究竟有什么意义呢?
      • 我们通过上文的分析其实可以知道,迭代器是通过cursor指针指向对应集合元素来挨个获取集合中元素的,每次获取对应元素后cursor值+1指向下一个元素,直到集合最后一个元素。
      • 那么如果在迭代器获取元素的过程中,集合中元素的个数突然改变,那么下一次获取元素时,cursor能否正确的指向集合的下一个元素就变得未知了,这种不确定性有可能导致迭代器工作出现意想不到的问题。
      • 为了防止在将来某个时间任意发生不确定行为的风险,我们在使用迭代器的过程中不允许修改集合结构(也可以说是不允许修改元素个数),否则迭代器会抛出异常结束程序。

    • 3.2 那如果如果遇到需要在遍历集合的同时修改集合结构的需求如何处理?

      • 3.2.1 在迭代器迭代的过程中,我们虽然不能通过集合直接增删元素,但是其实迭代器中是有这样的方法可以实现增删的。

        • 通过ArrayList中iterator()方法返回的Itr迭代器对象包含有一个remove方法:

          public void remove() {
              if (lastRet < 0)
                  throw new IllegalStateException();
              checkForComodification();
          
              try {
                  ArrayList.this.remove(lastRet);
                  cursor = lastRet;
                  lastRet = -1;
                  expectedModCount = modCount;
              } catch (IndexOutOfBoundsException ex) {
                  throw new ConcurrentModificationException();
              }
          }
          
        • 除了通过iterator()方法返回的Itr迭代器对象之外,我们可以获取Itr迭代器的子类对象ListItr,ListItr中有添加元素的add方法:

          public void add(E e) {
              checkForComodification();
          
              try {
                  int i = cursor;
                  ArrayList.this.add(i, e);
                  cursor = i + 1;
                  lastRet = -1;
                  expectedModCount = modCount;
              } catch (IndexOutOfBoundsException ex) {
                  throw new ConcurrentModificationException();
              }
          }
          
      • 以上两个方法在增删完元素后都对指针cursor进行了相应的处理,避免了出现迭代器获取元素的不确定行为。

      • 3.2.2 异常是迭代器抛出的,那么我们除了可以使用迭代器遍历集合,还可以使用其他方法,比如:

        • 属于List体系的集合我们可以使用用普通for循环,通过索引获取集合元素的方法来遍历集合,这个时候修改集合结构是不会出现异常的。

          public static void main(String[] args){
              ArrayList<String> list = new ArrayList<String>();
              list.add("Java");
              list.add("Hello");
              list.add("World");
          
              for (int i = 0; i < list.size(); i++) {
                  String element = list.get(i);
                  if(element.equals("Java")){
                      /* 注意:
                       * 当集合中增删元素后 i 索引的指向元素有可能发生变化,
                       * 我们通常会在增删元素的同时让i变量也随之变化,
                       * 从而使 i 能正确指向下一个元素:list.remove(i--);
                       */
                      list.remove(i);
                  }
              }
          }
          
        • 那么不属于List体系的集合,我们也可通过单列集合顶层接口Collction中定义过的toArray方法将集合转为数组,这个时候就不需要担心出现并发修改异常了。

    4. 其他相关问题

    • 4.1 foreach循环和迭代器

      • foreach循环也就是我们常说的增强for循环,其实foreach循环的底层是用迭代器实现的
      • 我们可以通过断点调试操作如下范例代码证明上面的观点:

        public static void main(String[] args){
            ArrayList<String> list = new ArrayList<String>();
            list.add("Java");
            list.add("Hello");
            list.add("World");
        
            for (String s : list) {
                System.out.println(s);//在此行代码打上断点,然后开启debug运行程序
            }
        }
        
        • 在输出语句这一行打上断点,当程序执行到输出语句这一行时,eclipse跳入debug视图
        • 接着按下F6结束这一步,debug上显示执行for循环上的代码,此时按下F5进入代码,会发现程序的执行来到了ArrayList类中内部类Itr中的hasNext()方法中。
          • 由此可见,foreach循环底层是用迭代器来实现的。
      • 既然foreach底层是用迭代器实现的,那么就意味着:
        • 我们不能在foreach中对集合结构进行修改。否则有可能出现并发修改异常

    • 4.2 当迭代至集合倒数第二个元素的同时,删除集合元素不会导致并发修改异常

      • 这是一个很有意思的问题,我们先来一段范例代码:

        public static void main(String[] args){
            ArrayList<String> list = new ArrayList<String>();
            list.add("Java");
            list.add("Hello");
            list.add("World");
        
            for (String s : list) {
                if(s.equals("Hello")){
                    list.remove("Java");
                }
            }
            System.out.println(list);//控制台输出:[Hello, World]
        }
        
        • 上面的代码在foreach中当迭代至到处第二个元素”Hello”的时候,我们删除了元素”Java”,但是并没有出现并发修改异常,控制台输出了剩余的两个元素也证明这次删除确实成功了。
        • 如果不是迭代至倒数第二个元素时删除元素同样会导致异常的产生,这又是为什么呢?
      • 原因解释:
        • 集合中倒数第二个元素的索引为size - 2,当迭代器取出集合倒数第二个元素的时候,cursor指向的位置会向右移动一位,值会变为size - 1;
        • 如果此时通过集合去删除一个元素,集合中元素个数会减一,所以size值会变为size - 1;
        • 当迭代器试图去获取最后一个元素的时候,会先判断是否还有元素,调用hasNext()方法,上文中已经分析过,hasNext()方法会返回cursor!=size,但是此时的cursor和此时的size值都等于删除之前的size - 1,两者相等,那么hasNext()方法就会返回false,迭代器就不会再调用next方法获取元素了。
    展开全文
  • 并发修改异常原理与解决方法

    千次阅读 2017-06-20 17:22:04
    什么是并发修改异常: 当我们在遍历实现了collection接口与iterator接口的集合时(List、Set、Map), 我们可以通过遍历索引也可以通过迭代器进行遍历。在我们使用迭代器进行遍历集合的时候,会获取到当前集合的迭代...

    什么是并发修改异常:

    当我们在遍历实现了collection接口与iterator接口的集合时(List、Set、Map), 我们可以通过遍历索引也可以通过迭代器进行遍历。在我们使用迭代器进行遍历集合的时候,会获取到当前集合的迭代对象。在里面有封装了迭代器的remove方法与集合自带的remove方法,如果我们调用迭代器对象的remove方法是没问题的,但是当我们调用集合自带的remove方法时,就会产生ConcurrentModificationException 并发修改异常。也就是说,当我们通过非迭代器进行遍历集合的时候,是不允许集合本身在结构上发生变化的。

    示例代码如下:

     

    package iteratorDemo;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class ArrayListDemo {
    	public static void main(String[] args) {
    		List<String> list = new ArrayList<String>();
    		for (int i = 0; i < 10; i++) {
    			list.add(String.valueOf(i));
    		}
    		System.out.println("遍历之前集合的长度为:");
    		System.out.println(list.size());
    		//获取集合的迭代器对象
    		Iterator<String> iterator = list.iterator();
    		//打印出迭代器的地址
    		System.out.println(iterator.toString());
    		//用iterator迭代器进行遍历
    		while(iterator.hasNext()) {
    			String next = iterator.next();
    			System.out.println(next);
    			/**
    			 * 在使用迭代器的同时进行集合结构的变化
    			 */
    			//list.remove(0);
    			if(Integer.parseInt(next)%2==0) {
    				//调用迭代器本身的remove方法
    				iterator.remove();
    			}
    		}
    		System.out.println("遍历之后集合的长度为:");
    		System.out.println(list.size());
    		
    		for (String string : list) {
    			System.out.println("开始进行增强for循环下的删除操作");
    			list.remove(0);
    		}
    	} 
    }
    

     

    运行之后的结果为:

     

    遍历之前集合的长度为:
    10
    java.util.ArrayList$Itr@5ecb5608
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    遍历之后集合的长度为:
    5
    开始进行增强for循环下的删除操作
    Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at iteratorDemo.ArrayListDemo.main
    (ArrayListDemo.java:35)

    在上面通过增强for循环实现将集合进行遍历,也产生了并发修改异常,因为在底层也是调用的集合本身的remove。

    如果在以后在迭代器遍历时,需要对集合进行增删操作时,要调用迭代器本身的remove方法。

     

    展开全文
  • 集合的并发修改异常理解

    千次阅读 2018-02-03 23:20:40
    java.util.ConcurrentModificationExcepton 并发修改异常 /* 集合中的并发修改异常的理解 1、为什么会出现并发修改异常呢?  因为集合在遍历时,你突然修改了集合中的一个值,或添加,引起索引混乱出现并发异常 ...
  • 如果使用Iterator()迭代元素, 在迭代过程中不可以删除元素, 否则会出现并发修改异常. 迭代元素可增减, 使用listIterator()方法. Iterator it=list.listIterator(); Iterator it=list.iterator(); while(it.hasNext()...
  • 检查迭代器元素修改的次数是否和集合元素修改的此处一样,如果不一样则会抛出并发修改异常 int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this....
  • HashMap并发修改异常解决办法

    千次阅读 2017-04-20 19:18:56
    我在循环读取hashmap里的内容时,在循环中又在另外一个线程对hashmap...翻译过来就是并发修改异常,上网找了下资料,解决方法如下: 调用HashMap的reomve方法时会出现 java.util.ConcurrentModificationExcepti
  • 因为foreach的底层就是迭代器。
  • 并发修改异常 A:出现的现象 迭代器遍历集合,集合修改集合元素 B:原因 迭代器是依赖于集合的,而集合的改变迭代器并不知道。 C:解决方案 a:迭代器遍历,迭代器修改(ListIterator) 元素添加在刚才迭代...
  • serise用数字下标索引 import pandas as pd data = {'hah':[1,2,9], '数量':[3,2,5], '价格':[10,9,8]} df = pd.DataFrame(data) df import numpy as np def panduan(x): x_mean = np.mean(x) ...
  • 并发修改异常产生的原因及解决方案 A:案例演示 需求:我有一个集合,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。 List list = new ArrayList(); list.add("a...
  • import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /*  *   *  ... * 当方法检测到对象的并发修改,但不允许这种修改时,
  • Android并发修改异常:java.util.ConcurrentModificationException 异常原因……分析解决……个人理解……部分异常代码示例……
  • foreach remove 时出现并发修改异常

    千次阅读 2012-01-05 11:16:20
    } 直接remove并发异常 可改为: List<Overlay> overlays = mapView.getOverlays(); Overlay overlayToDel = null; for (Overlay overlay : overlays) { if (overlay instanceof...
  • * 迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。 * 其实这个问题描述的是:迭代器遍历元素的时候,通过集合是不能修改元素的。 * ...
  • 在今天看视频的时候讲到修改集合元素的时候会出现并发修改异常就是像这样ArrayList<Integer> list = new ArrayList(); list.add(1); for(int i:list){ list.remove(i); }此时就会报并发修改异常 因为你在进入循环的...
  • 小白一个,求大神回答。 /* 请按如下要求编写多线程程序: 1.得到一个随机的整数n,创建n个子线程对象; 2.要求在子线程中把当前线程的名称作为元素添加一个集合中; 3.当n个线程的名称都添加到集合中,遍历... ...
  • 列表迭代器与并发修改异常异常发生条件解决方案列表迭代器(ListIterator)Listlterator中的常用方法Listlterator与Iterator代码样例 名词解释 modCount :实际修改集合的次数 expectedModCount :预期修改集合的次数 ...
  • 当迭代器操作的时候,如果发现和集合不一样,则抛出异常(并发修改异常) Exception in thread "main" java.util.ConcurrentModificationException:并发修改异常 解决方案:  方式1: 不使用迭代器  方式2: 迭代...
  • 在设置-应用-权限管理中禁用读写手机存储,app出现异常,用户掉线 what?什么鬼? 马上自测,果然,用户的登录状态变成了离线。。。 而实例对象也被置为null。。。   处理办法: 应用被系统杀死时,会自...
  • 问题: 我有一个集合,如下,请问,我想...ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。 产生的原因: 迭代器是依赖于集合而存在的,在判断成功后,集合
  • Exception in thread “Thread-3” java.util.ConcurrentModificationException 并发修改异常 即:多个线程同时修改一个对象 解决方案:使用java锁机制,对同一个对象使用同一个锁
  • 在对数据库进行一些操作的时候我们可能会遇到以下的一些问题: ...数据冗余(想修改一个属性,就要更新多行数据) 插入异常(想要插入数据,结构因为表设计的问题,导致不能成功插入) 删除异常(只想删除其中...
  • 数据冗余(想修改一个属性,就要更新多行数据) 插入异常(想要插入数据,结构因为表设计的问题,导致不能成功插入) 删除异常(只想删除其中的某些数据 ,结果把不该删的也删了) 更新异常(想更新一条数据,结果工作量大,还...
  • java异常处理中的返回值

    千次阅读 2018-08-16 17:51:31
    java代码中,有各种各样的try-catch代码用来捕获各种异常。那么在try-catch代码中,返回值是如何处理的呢?先看看下面的代码 public static int test_finally() { int x; try { x = 1; //int y = ...
  • 数据冗余(想修改一个属性,就要更新多行数据) 插入异常(想要插入数据,结构因为表设计的问题,导致不能成功插入) 删除异常(只想删除其中的某些数据 ,结果把不该删的也删了) 更新异常(想更新一条数据,结果工作量大,还...
  • 修改了docker容器中的配置信息,由于配置文件写错,或者配置文件格式错误等原因,导致容器无法再次启动 方法一 docker容器的一些配置信息一般在var/lib/docker/overlay下面,我们到此目录找到对应的配置,修改后...
  • tp5修改默认错误页面

    千次阅读 2018-08-06 14:24:39
    一旦抛出了HttpException异常,可以支持定义单独的异常页面的模板地址,只需要在应用配置文件中增加: 'http_exception_template' =&gt; [ // 定义404错误的重定向页面地址 404 =&gt; APP_PATH.'404....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,105,533
精华内容 442,213
关键字:

修改异常