hibernate更新報錯 java.util.ConcurrentModificationException

項目中 在一個Map中存着用戶列表.. 當前有個需求需要把Map中所有的用戶信息進行更新..首先很容易想到的是這樣的寫法.
Map map = new HashMap();
		map.put("A", "abc");
		map.put("B", "123");
		map.put("C", "321");
		Iterator it = map.entrySet().iterator();
		while ( it.hasNext() ) {
			Object user = (Object) it.next();
			System.out.println(user);
                        user.update(user);
               }

但是當第一次執行完畢.第二次的時候在這一行會

	Object user = (Object) it.next();

報錯.

java.util.ConcurrentModificationException


首先看api是如何解釋這個exception的..

當方法檢測到對象的併發修改,但不允許這種修改時,拋出此異常.

例如,某個線程在 Collection 上進行迭代時,通常不允許另一個線性修改該 Collection。通常在這些情況下,迭代的結果是不確定的。如果檢測到這種行爲,一些迭代器實現(包括 JRE 提供的所有通用 collection 實現)可能選擇拋出此異常。執行該操作的迭代器稱爲快速失敗 迭代器,因爲迭代器很快就完全失敗,而不會冒着在將來某個時間任意發生不確定行爲的風險。

注意,此異常不會始終指出對象已經由不同 線程併發修改。如果單線程發出違反對象協定的方法調用序列,則該對象可能拋出此異常。例如,如果線程使用快速失敗迭代器在 collection 上迭代時直接修改該 collection,則迭代器將拋出此異常。

注意,迭代器的快速失敗行爲無法得到保證,因爲一般來說,不可能對是否出現不同步併發修改做出任何硬性保證。快速失敗操作會盡最大努力拋出 ConcurrentModificationException。因此,爲提高此類操作的正確性而編寫一個依賴於此異常的程序是錯誤的做法,正確做法是:ConcurrentModificationException 應該僅用於檢測 bug。



看到有點暈乎.那麼久google下這個錯誤


Iterator 是工作在一個獨立的線程中,並且擁有一個 mutex 鎖。 Iterator 被創建之後會建立一個指向原來對象的單鏈索引表,當原來的對象數量發生變化時,這個索引表的內容不會同步改變,所以當索引指針往後移動的時候就找不到要迭代的對象,所以按照 fail-fast 原則 Iterator 會馬上拋出 java.util.ConcurrentModificationException 異常。

Iterator是工作在一個獨立的線程中,並且擁有一個 mutex鎖,就是說Iterator在工作的時候,是不允許被迭代的對象被改變的。Iterator被創建的時候,建立了一個內存索引表(單鏈表),這 個索引表指向原來的對象,當原來的對象數量改變的時候,這個索引表的內容沒有同步改變,所以當索引指針往下移動的時候,便找不到要迭代的對象,於是產生錯 誤。List、Set等是動態的,可變對象數量的數據結構,但是Iterator則是單向不可變,只能順序讀取,不能逆序操作的數據結構,當 Iterator指向的原始數據發生變化時,Iterator自己就迷失了方向


對就是這樣的.. 說下我個人的簡單理解.

目前我這個項目是用的hibernate去執行更新. 開着二級緩存.

首先hibernate執行sql 更新完畢後 此時hibernate內存中的值也就沒有存在的意義了.此時這些數據由持久狀態轉換爲了瞬時狀態.

( hibernate分爲三中狀態: 1. 瞬時狀態 2.持久狀態 3.離線狀態 )


簡單說下這三種狀態:

      1.瞬時狀態(臨時狀態)  session和數據庫都沒有對應的記錄存在

      2.持久狀態  session和數據庫都有對應的記錄存在

      3.離線狀態(遊離狀態)  session中有記錄 而數據庫沒有記錄



看了這個圖應該會明白也一些的..  簡單說就是

 map此時是持久狀態

當執行update後 hibernate也要對緩存進行更新(前提:如果配置了inverse=true的話。或則hibernate其他機制) 

此時回到了原題 就是hibernate要對這個map中的進行remove 所以在第二次執行it.next的時候就報錯了..

另外說下 這個他實現了fail-fast 原則 這個可以自己去看一下..



ps: 如果大家能有好的簡單的說法 麻煩大家告訴我下



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章