2013-07-01 52 views
-2

我不明白爲什麼這個方法拋出一個異常:奇怪ConcurrentModificationException的行爲

public void add(Object obj){ 
    gameObjects.add(obj); //here the exception happens 
} 

...而這一次沒有:

public void add(Object obj){ 
    gameObjects.add(obj); // no exception actually happens here 
    gameObjects.remove(obj); 
} 

爲什麼會發生這種情況,考慮是它是一個運行時異常?

例外:

Exception in thread "Thread-0" java.util.ConcurrentModificationException 
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source) 
    at java.util.ArrayList$Itr.next(Unknown Source) 
    at threads.Main.tick(Main.java:181) 
    at threads.Main.run(Main.java:104) 

的方法被稱爲用於物體內部的蜱方法。

gameObjects不爲空:

List<Object> gameObjects = new ArrayList<Object>(128); 
+9

這是不是足夠的信息。首先,什麼是例外。此外,這些電話的上下文是什麼?誰調用代碼以及如何? –

+0

gameObjects是什麼類型? – Cemafor

+0

什麼是'gameObjects'?它是否爲空? – NINCOMPOOP

回答

3

貌似你試圖將其添加在一個循環。 Java不允許這樣做。如果你使用相同的方法添加然後刪除,那麼你並沒有太多的工作,淨變化沒有什麼不同,所以你不想在循環中改變集合。

如果你想要它添加它,你必須使用迭代器。

2

第一種方法會拋出異常,因爲您正在修改循環中的某個集合。第二個並不是因爲收集沒有淨變化;你添加然後刪除一個元素。

請注意,它不是檢查ConcurrentModificationExceptionadd方法;相反,在每次循環迭代結束時檢查集合是否有任何修改。

+0

但是'Add'方法調用不可能知道下面的'Remove'方法調用,所以它不能推斷淨更改並決定不引發異常。我錯過了什麼嗎? –

+1

@TheodorosChatzigiannakis'add'方法不是檢查併發修改的方法。 – arshajii

+0

哦,你是對的,我只是看到了堆棧跟蹤。無論如何,我真傻。 –

0

根據doc

此異常可能由已檢測到的併發 修改一個對象的當這樣的修改是不允許的方法被拋出。

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

0

遍歷期間不能更改相同的object

JavaDoc說的

的此類的迭代器返回和的ListIterator迭代 方法是快速失敗的:如果列表在任何 時間,通過結構改性創建迭代器之後,以任何方式,除了 迭代器自己的remove或add方法,迭代器將拋出一個 ConcurrentModificationException。

欲瞭解更多詳情,請點擊這些鏈接。他們可能會幫助你學習。

Concurrent Modification exception http://docs.oracle.com/javase/6/docs/api/java/util/ConcurrentModificationException.html