日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

ConcurrentModificationException异常解决办法

發(fā)布時(shí)間:2023/11/29 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ConcurrentModificationException异常解决办法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

今天在寫一個(gè)帶緩存功能的訪問(wèn)代理程序時(shí)出現(xiàn)了java.util.ConcurrentModificationException異常, 因?yàn)樵摦惓J欠遣东@型異常而且很少見(jiàn),所以費(fèi)了些時(shí)間才找到問(wèn)題所在,原來(lái)在通過(guò)Iterator進(jìn)行遍歷的時(shí)候,如果直接對(duì)HashMap進(jìn)行操作后,再繼續(xù)用之前的Iterator進(jìn)行遍歷就會(huì)出現(xiàn)這個(gè)異常,表示其HashMap已經(jīng)被修改。

源程序代碼片段如下:caches為一個(gè)HashMap對(duì)象

1 String sameKeyPart = accesserClassName + "@" + methodName + "@" + parameterKeyString + "@"; 2 Iterator keys = caches.keySet().iterator(); 3 String key = null; 4 while (keys.hasNext()) ...{ 5 key = (String) keys.next(); 6 if (key.startsWith(sameKeyPart)) ...{ 7 caches.remove(key); 8 } 9 }

?

?

?

解決辦法為通過(guò)其相應(yīng)的Iterator進(jìn)行刪除就可以了,修改后代碼片段如下:

1 String sameKeyPart = accesserClassName + "@" + methodName + "@" + parameterKeyString + "@"; 2 Iterator keys = caches.keySet().iterator(); 3 String key = null; 4 while (keys.hasNext()) ...{ 5 key = (String) keys.next(); 6 if (key.startsWith(sameKeyPart)) ...{ 7 keys.remove(); 8 } 9 }

?

2、

撰寫多線程代碼時(shí),你遇到過(guò)多少次下面的提示:
Exception in thread "main" java.util.ConcurrentModificationException??
?

這個(gè)異常產(chǎn)生的原因有幾個(gè)。一是直接對(duì)集合調(diào)用刪除操作而不是在枚舉器上。二是不同的線程試圖對(duì)集合進(jìn)行增刪操作的時(shí)候。

這個(gè)解決辦法的第一步就是同步代碼,使得你在枚舉的時(shí)候其它的線程不能增刪記錄。但是如果每個(gè)枚舉過(guò)程要進(jìn)行復(fù)雜的計(jì)算或者是數(shù)據(jù)庫(kù)訪問(wèn)的一部分的話,這個(gè)同步就會(huì)導(dǎo)致可怕的后果。為了減少負(fù)面影響,可以拷貝一個(gè)只讀的枚舉器,去掉同步,然后采用下列代碼所示的方法:

1 private List list; 2 public void add(Object obj) { 3 synchronized(list) { 4 list.add(obj); 5 } 6 } 7 public void perform( ) { 8 Iterator iterator = null; 9 synchronized(list) { 10 iterator = new CopiedIterator(list.iterator( )); 11 } 12 while(iterator.hasNext( )) { 13 // perform resource or cpu hungry work 14 } 15 }

?

重要的是記住,CopiedIterator不是一個(gè)克隆,只是一個(gè)只讀的拷貝,所以它并沒(méi)有保持原有的全部功能。最重要的是,不能再調(diào)用CopiedIterator.remove方法了。CopiedIterator.remove的實(shí)現(xiàn)如下:

1 public class CopiedIterator implements Iterator { 2 private Iterator iterator = null; 3 public CopiedIterator(Iterator itr) { 4 LinkedList list = new LinkedList( ); 5 while(itr.hasNext( )) { 6 list.add(itr.next( )); 7 } 8 this.iterator = list.iterator( ); 9 } 10 public boolean hasNext( ) { 11 return this.iterator.hasNext( ); 12 } 13 public void remove( ) { 14 throw new UnsupportedOperationException("This is a read-only iterator. 15 "); 16 } 17 public Object next( ) { 18 return this.iterator.next( ); 19 } 20 }

枚舉器的只讀拷貝將用在同步狀態(tài)上的時(shí)間減少到最小,因此可以增強(qiáng)全局的效率。

3、

當(dāng)使用 fail-fast iterator 對(duì) Collection 或 Map 進(jìn)行迭代操作過(guò)程中嘗試直接修改 Collection / Map 的內(nèi)容時(shí),即使是在單線程下運(yùn)行,??java.util.ConcurrentModificationException 異常也將被拋出。
  Iterator 是工作在一個(gè)獨(dú)立的線程中,并且擁有一個(gè) mutex 鎖。 Iterator 被創(chuàng)建之后會(huì)建立一個(gè)指向原來(lái)對(duì)象的單鏈索引表,當(dāng)原來(lái)的對(duì)象數(shù)量發(fā)生變化時(shí),這個(gè)索引表的內(nèi)容不會(huì)同步改變,所以當(dāng)索引指針往后移動(dòng)的時(shí)候就找不到要迭代的對(duì)象,所以按照 fail-fast 原則 Iterator 會(huì)馬上拋出 java.util.ConcurrentModificationException 異常。

  所以 Iterator 在工作的時(shí)候是不允許被迭代的對(duì)象被改變的。但你可以使用 Iterator 本身的方法 remove() 來(lái)刪除對(duì)象, Iterator.remove() 方法會(huì)在刪除當(dāng)前迭代對(duì)象的同時(shí)維護(hù)索引的一致性。

  有意思的是如果你的 Collection / Map 對(duì)象實(shí)際只有一個(gè)元素的時(shí)候, ConcurrentModificationException 異常并不會(huì)被拋出。這也就是為什么在 javadoc 里面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.

1??import java.util.*;???
2????
3??public final class MyTest???
4??{???
5??????private static HashMap p_mapList = new HashMap(2);???
6??????private MyTest(){}???
7??????public static void init(){???
8??????????// If only there are more than one element in Map,????
9??????????// the ConcurrentModificationException will not be???
10??????????// thrown.???
11??????????p_mapList.put(new String("hello"),new String("world"));???
12??????????p_mapList.put(new String("goto"),new String("hell"));???
13??????}???
14??????public static void clear() throws Exception{???
15??????????Iterator pTmpKeys = null;???
16??????????Long pTmpKeyLong;???
17??????????pTmpKeys = p_mapList.keySet().iterator();???
18??????????String pCurKey = null;???
19??????????String pCurObj = null;???
20??????????while(pTmpKeys.hasNext()){???
21??????????????pCurKey = (String) pTmpKeys.next();???
22??????????????pCurObj = (String) p_mapList.get(pCurKey);???
23????
24??????????????p_mapList.put(pCurKey,null);???
25??????????????// You can not remove element in Map object directly.???
26??????????????//p_mapList.remove(pCurKey);???
27??????????????// But you can remove current element by iterator itself.???
28??????????????pTmpKeys.remove();???
29????
30??????????????System.out.println(pCurKey + " removed.");???
31??????????}???
32??????????System.out.println(p_mapList.size() +????
33??????????????????????????????" entries left after iterator.");???
34??????????pTmpKeys = null;???
35??????}???
36??????public static void main(String[] args)???
37??????????????????????????????????throws Exception{???
38??????????MyTest.init();???
39??????????MyTest.clear();???
40??????}???
41??}??

?

轉(zhuǎn)載于:https://www.cnblogs.com/wslcs/p/4978233.html

總結(jié)

以上是生活随笔為你收集整理的ConcurrentModificationException异常解决办法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。