中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中ConcurrentModificationException異常警告怎么解決

發布時間:2022-06-02 16:20:50 來源:億速云 閱讀:213 作者:iii 欄目:大數據

這篇文章主要介紹“java中ConcurrentModificationException異常警告怎么解決”,在日常操作中,相信很多人在java中ConcurrentModificationException異常警告怎么解決問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”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()方法就會拋出異常,因為此時ListmodCount已經變為 了2,而expectedModCount仍然是3,所以會拋出ConcurrentModificationException異常;

解決方法

那么如何解決該問題呢?我們查看java.util.ArrayList.Itr(ArrayList中的Iterator實現)的源碼可以發現,在該迭代器中有一個remove方法可以 刪除當前迭代元素,而且會同時修改modCountexpectedModCount,這樣在進行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異常警告怎么解決”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

沙坪坝区| 阳泉市| 太仓市| 闻喜县| 永登县| 山东省| 马公市| 丰都县| 赞皇县| 隆子县| 平昌县| 株洲市| 琼中| 泸溪县| 弋阳县| 多伦县| 清原| 武乡县| 息烽县| 泰来县| 天峨县| 西充县| 沁水县| 绍兴市| 宿州市| 濮阳县| 安塞县| 汽车| 彭阳县| 梓潼县| 锦州市| 高阳县| 洞口县| 浙江省| 文登市| 天台县| 曲阳县| 兴山县| 万全县| 宜昌市| 棋牌|