2016-04-07 35 views
-1

我基本上是做以下:
創建一個對象(例如一個武器對象),即自動將該對象添加到列表關閉所有這些類型的對象(ArrayList<Weapons>)的。的Java ConcurrentModificationException的問題與班級

JPanel每10秒鐘繪製一個更新線程,該線程遍歷ArrayList<Weapons>。我也向另一臺機器上的服務器發送'問題',即詢問是否允許使用該武器。如果不是,則武器對象由客戶端計算機修改。但是,每當我修改它時,我都會收到ConcurrentModificationException。而不是崩潰,我真的希望它會在這一點上做,因爲改變武器對象的方法是在不同的線程上,整個程序就鎖定了。

我在這個程序中有1000多行代碼,並且有三個以上的線程可以訪問這個列表,所以如果你需要任何代碼,請問,但我現在不想發佈,因爲在我看來,這似乎像線程專家的一個小問題。

謝謝!

(對象被添加到對象列表>> JPanel的「更新器」線程不斷繪製所有對象每10個刻度... 服務器說該對象不被允許>>客戶端計算機上的線程刪除該對象(或切換一個布爾值,表示它不可見)>> ConcurrentModificationException)。

+0

您可能會發現[CopyOnWriteArrayList](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArrayList.html)有用。 – AJNeufeld

+2

ArrayList不是線程安全的。因此,一次只能有一個線程訪問它(迭代它稱爲「訪問它」)。或者你應該使用線程安全列表,如CopyOnWriteArrayList。如果同時訪問列表中的對象,它們也應該是線程安全的。 –

+2

另外,如果列表中包含的對象是武器,它應該是'List ',而不是'List ':每個對象都是** **武器。 –

回答

4

引述Javadoc of ArrayList

請注意,此實現不是同步的。如果多個線程同時訪問ArrayList實例,並且至少有一個線程在結構上修改了列表,則它必須在外部同步。

您描述了多個線程訪問列表,並且其中至少有一個線程正在修改它。所以,對列表的所有訪問必須在相互同步的塊中完成。

例如重複列表:

synchronized (list) { 
    for (Weapons weapons : list) { 
    // ... 
    } 
} 

例如,從列表中刪除一個項目:

synchronized (list) { 
    list.remove(0); 
} 
+0

我試過這個。它的工作原理與列表中的迭代一樣,但仍然有外部線程只修改列表中的一個對象,從而引發異常。 – NeurologicalApex

0

我認爲你可以使用集合或列表,即java.util.Collections.synchronizedCollection(Collection<>)java.util.Collections.synchronizedList(List<>)的同步版本。另外,如果迭代列表並移除項目,請確保使用實現從迭代器啓用移除項目。一個好的候選人是java.util.ArrayList

其他技術是使用「監視器」,您可以聲明一個屬性,如:private static Object monitor = new Object();然後當代碼嘗試訪問列表時,保護synchronized(monitor)塊內的代碼。使用這種技術,你可以確保沒有其他線程能夠修改你的列表,直到沒有受保護的代碼運行。

請原諒我的英文:)。