亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么拋出ConcurrentModificationException以及如何調試它

為什么拋出ConcurrentModificationException以及如何調試它

慕標琳琳 2019-06-14 10:39:06
為什么拋出ConcurrentModificationException以及如何調試它我用的是Collection(A)HashMapJPA間接使用,但顯然代碼會隨機拋出一個ConcurrentModificationException..是什么導致了這一問題,我如何解決這個問題?也許是通過一些同步?下面是完整的堆棧跟蹤:Exception in thread "pool-1-thread-1" java.util.ConcurrentModificationException         at java.util.HashMap$HashIterator.nextEntry(Unknown Source)         at java.util.HashMap$ValueIterator.next(Unknown Source)         at org.hibernate.collection.AbstractPersistentCollection$IteratorProxy.next(AbstractPersistentCollection.java:555)         at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)         at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)         at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)         at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)         at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
查看完整描述

3 回答

?
隔江千里

TA貢獻1906條經驗 獲得超10個贊

這不是同步問題。如果正在迭代的基礎集合被Iterator本身以外的任何東西修改,就會發生這種情況。

Iterator it = map.entrySet().iterator();while (it.hasNext()){
   Entry item = it.next();
   map.remove(item.getKey());}

這將在第二次調用它.hasNext()時拋出一個ConcurrentModificationException。

正確的方法是

   Iterator it = map.entrySet().iterator();
   while (it.hasNext())
   {
      Entry item = it.next();
      it.remove();
   }

假設此迭代器支持Remove()操作。


查看完整回答
反對 回復 2019-06-14
?
慕桂英3389331

TA貢獻2036條經驗 獲得超8個贊

嘗試使用ConcurrentHashMap而不是普通的HashMap


查看完整回答
反對 回復 2019-06-14
?
侃侃無極

TA貢獻2051條經驗 獲得超10個贊

修改aCollection當迭代的時候Collection使用Iterator不允許大部分Collection上課。Java庫調用試圖修改Collection雖然迭代它是一個“并發修改”,但不幸的是,這表明唯一可能的原因是由多個線程同時進行修改,但事實并非如此。只使用一個線程,就可以為Collection(使用Collection.iterator(),或增強型for環路),開始迭代(使用Iterator.next(),或等效地進入增強體的主體for循環),修改Collection,然后繼續迭代。

為了幫助程序員,一些的實現Collection嘗試若要檢測錯誤的并發修改,請拋出ConcurrentModificationException如果他們發現了。但是,保證檢測到所有并發的修改通常是不可能的,也是不可行的。如此錯誤地使用Collection并不總是導致拋出ConcurrentModificationException.

.的文件ConcurrentModificationException說:

此異??赡苡蓹z測到對象的并發修改的方法引發,而這種修改是不允許的.

請注意,此異常并不總是指示對象已被不同線程并發修改。如果單個線程發出一系列違反對象契約的方法調用,該對象可能會拋出此異常.

請注意,通常情況下,不能保證快速失敗的行為在存在不同步并發修改的情況下提供任何硬的保證。失敗操作拋出ConcurrentModificationException在盡最大努力的基礎上。

請注意

的文件HashSetHashMapTreeSetArrayList課程上說:

[直接或間接地從該類返回的迭代器]失敗快速:如果[集合]在迭代器創建后的任何時候被修改,則除通過迭代器自身的Remove方法外,以任何方式修改Iterator拋出ConcurrentModificationException..因此,在并發修改的情況下,迭代器會迅速而干凈地失敗,而不是在未來某個未定的時間冒著任意的、不確定的行為的風險。

請注意,迭代器的快速失敗行為不能保證,一般來說,在不同步并發修改的情況下不可能提供任何硬的保證。失敗快速迭代器拋出ConcurrentModificationException在盡最大努力的基礎上。因此,編寫一個依賴于此異常的程序是錯誤的:迭代器的抗故障行為應該僅用于檢測bug。.

請再次注意,這種行為“不能保證”,而且僅僅是“在盡最大努力的基礎上”。

的幾種方法的文檔化。Map接口說明如下:

非并發實現應該覆蓋此方法,并在最大努力的基礎上拋出ConcurrentModificationException如果檢測到映射函數在計算期間修改此映射。并發實現應該覆蓋此方法,并在最大努力的基礎上拋出IllegalStateException如果檢測到映射函數在計算期間修改此映射,則計算將永遠不會完成。

請再次注意,檢測只需要“盡最大努力的基礎”,并且ConcurrentModificationException顯式地建議只用于非并發(非線程安全)類。

調試ConcurrentModificationException

因此,當您看到堆棧跟蹤是由于ConcurrentModificationException,您不能立即假定原因是不安全的多線程訪問Collection..你必須檢查堆棧跟蹤決定哪一類Collection拋出異常(類的方法將直接或間接拋出它),其中Collection對象。然后,您必須從可以修改對象的位置進行檢查。

  • 最常見的原因是修改

    Collection

    在增強的范圍內

    for

    循環在

    Collection

    ..僅僅因為你沒有看到

    Iterator

    對象在您的源代碼中并不意味著沒有

    Iterator

    那里!幸運的是,有一個錯誤的說法

    for

    循環通常在堆棧跟蹤中,因此跟蹤錯誤通常很容易。
  • 更棘手的情況是,當您的代碼在引用中傳遞到

    Collection

    對象。請注意

    不可修改

    收藏的視圖(如由

    Collections.unmodifiableList()

    )保留對可修改集合的引用,因此

    對“不可修改”集合的迭代可以引發異常。

    (修改已在其他地方完成)。其他

    意見

    你的

    Collection

    ,如

    子列表Map條目集

    Map密鑰集

    還保留對原始(可修改)的引用

    Collection

    ..這可能是一個問題,即使是線程安全。

    Collection

    ,如

    CopyOnWriteList

    不要假設線程安全(并發)集合永遠不會拋出異常。
  • 哪些操作可以修改

    Collection

    在某些情況下可能是意外的。例如,

    LinkedHashMap.get()修改其集合.

  • 最困難的情況是例外

    由多個線程并發修改造成的。

防止并發修改錯誤的編程

如果可能,將所有引用限制在Collection對象,因此它更容易防止并發修改。使.Collection a private對象或局部變量,并且不返回對Collection或者方法中的迭代器。這樣就容易得多了。在那里Collection可以修改。如果Collection將由多個線程使用,則確保線程訪問Collection只有適當的同步和鎖定。


查看完整回答
反對 回復 2019-06-14
  • 3 回答
  • 0 關注
  • 1682 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號