2011-02-28 70 views
9

根據運行時錯誤消息,異常發生在以下行中;迭代時發生Java「ConcurrentModificationException」運行時錯誤。()

VirusData v = iteratorVirusDB.next(); 

VirusData是一個構造函數和含有約每一個在數據庫中,如病毒的特定信息的重載的構造的類;

  • 字符串VNAME
  • 字符串vDefinition

  • 陣列與記號化定義(在xLength的基團隔開)
  • 陣列與LCS令牌重載
  • 浮動用級

<VirusData>類型的iteratorVirusDBVirusDB()的.iterator,如圖所示波紋管:

Iterator<VirusData> iteratorVirusDB = virusDB.iterator(); 

VirusDB是和<VirusData>類型的ArrayList其中I存儲病毒對象(此時名稱和def)以便我可以稍後使用它們。

ArrayList <VirusData> virusDB = new ArrayList<VirusData>(); 

而且隨着結束,在使用以上所有的解釋了這個方法出現錯誤:

private void selectDabataseMouseClicked(java.awt.event.MouseEvent evt) { 
    while(iteratorVirusDB.hasNext()) { 
     VirusData v = iteratorVirusDB.next();    //ERROR LINE 
     String vSig = v.signature;        
     v.tokens = tokenize.raw(vSig, true, tLength); 
     ... 
    } 
    ... 
} 

我真的可以做到對如何一些幫助和建議要解決這個問題才能讓程序成功運行。貝婁,完整堆棧跟蹤:

run: 
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException 
     at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372) 
     at java.util.AbstractList$Itr.next(AbstractList.java:343) 
     at project_clean.Main.selectDabataseMouseClicked(Main.java:275) 
     at project_clean.Main.access$100(Main.java:11) 
     at project_clean.Main$2.mouseClicked(Main.java:76) 
     at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:253) 
     at java.awt.Component.processMouseEvent(Component.java:6270) 
     at javax.swing.JComponent.processMouseEvent(JComponent.java:3267) 
     at java.awt.Component.processEvent(Component.java:6032) 
     at java.awt.Container.processEvent(Container.java:2041) 
     at java.awt.Component.dispatchEventImpl(Component.java:4630) 
     at java.awt.Container.dispatchEventImpl(Container.java:2099) 
     at java.awt.Component.dispatchEvent(Component.java:4460) 
     at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577) 
     at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4247) 
     at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168) 
     at java.awt.Container.dispatchEventImpl(Container.java:2085) 
     at java.awt.Window.dispatchEventImpl(Window.java:2478) 
     at java.awt.Component.dispatchEvent(Component.java:4460) 
     at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) 
     at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) 
     at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) 
     at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) 
     at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) 
     at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) 
     at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) 
+1

當您在結構上修改'ArrayList'時,迭代器變得無效。將迭代器保存爲成員之間的類狀態是可疑的。你爲什麼這樣做? – rlibby 2011-02-28 18:46:54

+0

我剛剛回答了一個關於ConcurrentModificationException的問題... http://stackoverflow.com/questions/5145135/java-util-concurrentmodificationexception-on-arraylist/5145156#5145156 – 2011-02-28 18:49:32

+0

嗯,我真的不知道迭代器是如何工作的我有隻是最近才發現它們存在,所以我只是通過反覆試驗來學習。所以如果我正確理解你,我不應該這樣做'迭代器 iteratorVirusDB = virusDB.iterator();'?但是,我怎樣才能迭代這樣的東西; 'VirusData v = virusDB.iterator()。next();'?感謝您的建議 – Carlos 2011-02-28 18:54:33

回答

11

顯而易見的解釋是,你必須在調用之間修改virusDB。在使用迭代器進行迭代時,不得修改向量(除非通過Iterator/ListIterator方法)。

的這段代碼將總是拋出ConcurrentModificationException

import java.util.*; 

class VirusData { 
} 

public class Test { 

    public static void main(String[] args) { 

     List<VirusData> list = new ArrayList<VirusData>() {{ 
      add(new VirusData()); 
      add(new VirusData()); 
      add(new VirusData()); 
     }}; 

     Iterator<VirusData> iterator = list.iterator(); 

     iterator.next(); 

     list.remove(0); 
     VirusData s = iterator.next(); 
    } 
} 

ConcurrentModificationException文檔:

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

請注意,此異常並不總是表示某個對象已被另一個線程同時修改。 如果單個線程發出一系列違反對象合約的方法調用,則該對象可能會拋出此異常。例如,如果一個線程在使用快速迭代器迭代集合的同時直接修改集合,迭代器將拋出此異常。

如果你的目的是在整個數據庫中的每個方法被調用一次迭代,我建議你做

private void selectDabataseMouseClicked(java.awt.event.MouseEvent evt) { 
    Iterator<VirusData> iteratorVirusDB = virusDB.iterator(); 
    while(iteratorVirusDB.hasNext()) { 
     VirusData v = iteratorVirusDB.next(); 
     String vSig = v.signature;        
+0

但是如果一個程序在這種情況下不斷地修改列表,那麼如何迭代它呢? – Carlos 2011-02-28 19:05:15

+1

你可以使用索引'i',用'yourList.size()'和'next()'''yourList.get(i)''替換'hasNext'。 – aioobe 2011-02-28 19:09:15

+0

非常感謝,你在答案中提出的建議很有效。然而,現在我很困惑,當我做'v.tokens = tokenize.raw(vSig,true,tLength);'*(在您的建議中忽略)*並不違反規則通過修改序列中的元素。或者「修改」一詞只適用於收集「大小」,以便在添加/刪除項目時僅僅違反詞彙? – Carlos 2011-02-28 19:21:57

0

當你修改它,而在遍歷它發生的併發修改例外同一時間。因此,如果您正在修改列表,請檢查您的代碼,並在迭代時發生。