您好,欢迎访问一九零五行业门户网

java中ConcurrentModificationException异常警告怎么解决

异常分析相信写过一些java代码的人都遇到过这个异常,一般都是由以下代码引起的:
import java.util.list; import java.util.arraylist; public class test{    public static void main(string[] args){      list<string> list = new arraylist<>();      list.add(123);      list.add(456);      list.add(789);      for(string obj : list){          list.remove(obj);      }    } }
上述代码最终会引发java.util.concurrentmodificationexception,那么为什么呢?首先我们将上述代码反编译,得到如下结果(如果对foreach语法糖比较了解可以忽略):
public class test {  public test();    code:       0: aload_0       1: invokespecial #1                  // method java/lang/object.<init>:()v       4: return    linenumbertable:      line 4: 0  public static void main(java.lang.string[]);    code:       0: new           #2                  // class java/util/arraylist       3: dup       4: invokespecial #3                  // method java/util/arraylist.<init>:()v       7: astore_1       8: aload_1       9: ldc           #4                  // string 123      11: invokeinterface #5,  2            // interfacemethod java/util/list.add:(ljava/lang/object;)z      16: pop      17: aload_1      18: ldc           #6                  // string 456      20: invokeinterface #5,  2            // interfacemethod java/util/list.add:(ljava/lang/object;)z      25: pop      26: aload_1      27: ldc           #7                  // string 789      29: invokeinterface #5,  2            // interfacemethod java/util/list.add:(ljava/lang/object;)z      34: pop      35: aload_1      36: invokeinterface #8,  1            // interfacemethod java/util/list.iterator:()ljava/util/iterator;      41: astore_2      42: aload_2      43: invokeinterface #9,  1            // interfacemethod java/util/iterator.hasnext:()z      48: ifeq          72      51: aload_2      52: invokeinterface #10,  1           // interfacemethod java/util/iterator.next:()ljava/lang/object;      57: checkcast     #11                 // class java/lang/string      60: astore_3      61: aload_1      62: aload_3      63: invokeinterface #12,  2           // interfacemethod java/util/list.remove:(ljava/lang/object;)z      68: pop      69: goto          42      72: return    linenumbertable:      line 6: 0      line 7: 8      line 8: 17      line 9: 26      line 10: 35      line 11: 61      line 12: 69      line 13: 72 }
将上述代码翻译出来等价于下列代码:
import java.util.list; import java.util.arraylist; import java.util.iterator; public class test{    public static void main(string[] args){      list<string> list = new arraylist<>();      list.add(123);      list.add(456);      list.add(789);      iterator<string> iterator = list.iterator();      while (iterator.hasnext()){          string obj = iterator.next();          list.remove(obj);      }    } }
然后我们查看iterator.hasnext()源码,可以发现第一行调用了checkforcomodification方法,我们查看这个方法:
final void checkforcomodification() {    if (modcount != expectedmodcount)        throw new concurrentmodificationexception(); }
在modcount != expectedmodcount这个条件成立的时候会抛出concurrentmodificationexception异常,那么这个条件是怎么成立的呢?
1、首先我们查看modcount的来源,可以发现modcount的值等于当前list的size,当调用list.remove方法的时候modcount也会相应的减1;
2、然后我们查看expectedmodcount的来源,可以看到是在构造iterator(这里使用的是arraylist的内部实现)的时候,有一个变量赋值,将modcount 的值赋给了expectedmodcount;
3、最后当我们执行循环调用list.remove方法的时候,modcount改变了但是expectedmodcount并没有改变,当第一次循环结束删除一个数据准 备第二次循环调用iterator.hasnext()方法的时候,checkforcomodification()方法就会抛出异常,因为此时list的modcount已经变为 了2,而expectedmodcount仍然是3,所以会抛出concurrentmodificationexception异常;
解决方法那么如何解决该问题呢?我们查看java.util.arraylist.itr(arraylist中的iterator实现)的源码可以发现,在该迭代器中有一个remove方法可以 删除当前迭代元素,而且会同时修改modcount和expectedmodcount,这样在进行checkforcomodification检查的时候就不会抛出异常了,该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();    } }
其中arraylist.this.remove(lastret);这一行会改变modcount的值,而后边会同步的修改expectedmodcount的值等于modcount的值;
现在修改我们开头的程序如下就可以正常运行了:
import java.util.list; import java.util.arraylist; import java.util.iterator; public class test{    public static void main(string[] args){      list<string> list = new arraylist<>();      list.add(123);      list.add(456);      list.add(789);      iterator<string> iterator = list.iterator();      while (iterator.hasnext()) {          system.out.println(移除: + iterator.next());          iterator.remove();      }    } }
以上就是java中concurrentmodificationexception异常警告怎么解决的详细内容。
其它类似信息

推荐信息