2012-07-10 110 views
2

我在下面一行發生錯誤。 我正在做添加到jsonarray的過程。 請幫幫我。我該如何解決這個錯誤java.util.ConcurrentModificationException

jsonArr=new JSONArray(); 
if(req.getSession().getAttribute("userses")!=null){ 
    String name=(req.getParameter("name")==null?"":to_EnglishName(req.getParameter("name").toUpperCase())); 
    if(!name.equals("")){ 
     for(Book c:GlobalObjects.bookList){ 
      if(c.getBookName().startsWith(name)){ 
        jsonObjec=new JSONObject(); 
        jsonObjec.put("label",c.getBookName()); 
        jsonObjec.put("value", c.getId()); 
        jsonArr.add(jsonObjec);//java.util.ConcurrentModificationException 
      } 
     } 
    } 
} 
jsonArr.write(res.getWriter()); 
+0

你嘗試過這麼遠嗎?你讀過ConcurrentModificationException的JavaDoc嗎? – 2012-07-10 06:33:54

+0

你是否遺漏了一些代碼,你實際上是在迭代你添加項目的JSONArray? – Confusion 2012-07-10 06:42:30

回答

11

這是我在重新編程時經常遇到的錯誤。這個例外的原因或細節非常清楚。在迭代過程中不允許修改集合(您正在添加一個新元素)。至少語法for不支持這樣做。

要解決您的問題,有兩種方法,我認爲它很簡單。

1)。而不是使用for語句來循環,更好的方法是使用迭代器來避免ConcurrentModificationException。

Iterator<Book> iterator = bookList.iterator(); 
    while(iterator.hasNext()){ 
     Book c = iterator.next(); 
     if(c.getBookName().startsWith(name)){ 
       jsonObjec=new JSONObject(); 
       jsonObjec.put("label",c.getBookName()); 
       jsonObjec.put("value", c.getId()); 
       jsonArr.add(jsonObjec); 
     } 
    } 

2)。同時循環它,不要添加它。

 List list = new ArrayList<>(); 
    for(Book c:GlobalObjects.bookList){ 
     if(c.getBookName().startsWith(name)){ 
       jsonObjec=new JSONObject(); 
       jsonObjec.put("label",c.getBookName()); 
       jsonObjec.put("value", c.getId()); 
       list.add(jsonObjec);//java.util.ConcurrentModificationException 
     } 
    } 
    jsonArr.addAll(list); 
+0

回覆太描述性了。感謝 – aliplane 2012-07-10 09:00:26

+0

你的意思是描述性的? – 2012-07-10 09:03:29

+0

是非常有幫助:) – aliplane 2012-07-10 09:16:19

0

你是從另一個線程訪問jsonArr嗎?即在您同時修改jsonArr時迭代。

如果在迭代迭代時同時修改集合,則會引發ConcurrentModificationException。

+0

devsundar說,除非jsonArr被多線程訪問,否則這不應該導致CME。是嗎? – MJB 2012-07-10 06:27:09

+0

從代碼我看到,jsonArr只被修改,並沒有在同一時間被訪問。如果鋁飛機在所提到的線上獲得了CME,那麼應該從另一個位置或線程修改jsonArr。 – 18bytes 2012-07-10 06:29:59

2

當您迭代集合並且修改循環中的相同集合時,會發生ConcurrentModificationException。給定的代碼片段沒有顯示,所以在修改集合上面或下面有其他內容。嘗試在實例化它的地方聲明jsonArr。

一個可能的原因可能是jsonArr實例Object是類級別並且被多個線程訪問。聲明jsonArr對象的實例化位置。

編輯:使jsonArr成爲局部變量。

+0

訪問Servlet中的代碼。我使用自動完成功能。 – aliplane 2012-07-10 07:49:26

+0

在多線程環境(如Web應用程序)中進行編碼時,請將變量的作用域儘可能保持爲本地。你不會遇到這樣的問題。 – devang 2012-07-10 14:10:03

3

要解決此問題,請確保If your collection is not thread safe then it must not get modified with another thread when some other thread is iterating over this collection

有兩種可能的方法來解決這個問題 -

1)一種解決方案是將所有的訪問同步到集合

2)使用線程安全的集合像CopyOnWriteArrayList

從Java文件 -

這種異常可能會被檢測到併發的 修改對象的方法拋出,修改是不允許的。

例如,一個線程修改一個 集合,而另一個線程正在迭代它時,通常是不可能的。通常,在這些情況下,迭代的結果是不確定的。某些 迭代器實現(包括由JRE提供的所有實現集合 實現中的那些實現)可能會選擇拋出此異常(如果檢測到此行爲)。這樣做的迭代器是 ,稱爲失敗快速迭代器,因爲它們快速且乾淨地失敗,而在未來未確定的 時間冒着任意的非確定性行爲冒險。

0

或者使用的ListIterator,它允許迭代和修改同一個列表

http://docs.oracle.com/javase/6/docs/api/java/util/ListIterator.html

+1

只有鏈接的答案是不鼓勵的,所以答案應該是搜索解決方案的終點(而另一個引用的中途停留時間往往會過時)。請考慮在此添加獨立的摘要,並將鏈接保留爲參考 – Alex 2013-09-25 12:14:59

0

而且另一種方式是存在的,即 insted的經過實際列表中,我們可以通過列表的克隆爲迭代。

listForIteration = list.clone();

//做手術..

0

只使用java.util.concurrent.CopyOnWriteArrayList

List<String> empList = new CopyOnWriteArrayList<>(); 
empList.add("Mojtaba"); 
empList.add("Mojtabye"); 
empList.add("Yeganeh"); 

for (String item : empList) { 
    System.out.println(item); 
    empList.add("test"); 
} 
相關問題