2014-12-02 237 views
-3

我有這樣的代碼:的CopyOnWriteArrayList奇怪的錯誤

int rnd1=Rnd.get(players.size()); 
int rnd2=Rnd.get(players.size()); 

while(rnd2==rnd1) 
    rnd2=Rnd.get(players.size()); 


for(L2PcInstance player : players) 
{ 
    if(player != players.get(rnd1) && player != players.get(rnd2)) 
      players.remove(player); 
} 

而且我有這樣的錯誤:

Exception in thread "GeneralSTPool-8" java.lang.ArrayIndexOutOfBoundsException: 2 at java.util.concurrent.CopyOnWriteArrayList.get(Unknown Source) at java.util.concurrent.CopyOnWriteArrayList.get(Unknown Source) at net.sf.l2j.gameserver.model.RandomFight.pickPlayers(RandomFight.java:89) at net.sf.l2j.gameserver.model.RandomFight$pickPlayers.run(RandomFight.java:270) at net.sf.l2j.gameserver.ThreadPoolManager$RunnableWrapper.run(ThreadPoolManager.java:85) at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) at java.util.concurrent.FutureTask.run(Unknown Source) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)

這到底是怎麼回事? 89行是這樣的:for(L2PcInstance player : players)。 這不應該出現,因爲rnd.get()是從0players.size() - 1

+0

從列表中移除項目後,列表不再相同。 – kiheru 2014-12-02 23:33:25

+0

@kiheru雖然這是一個COW列表,但應該沒有問題 – fge 2014-12-02 23:37:15

+0

@fge當訪問索引越界時,COW仍然可以拋出異常。這不是併發修改異常 – kiheru 2014-12-02 23:38:13

回答

0

意圖似乎從列表中刪除除了兩個選定的玩家以外的所有玩家。有更簡單的方法來做到這一點。例如:

players.retainAll(Arrays.asList(players.get(rnd1), players.get(rnd2)); 

這還沒有與併發修改的問題,這是你使用CopyOnWriteArrayList的原因的情況。

正如在評論中已經說過的那樣,錯誤的原因是:玩家指數是在初始列表中生成的,並且在那時它們確實是有效的。刪除循環會減小列表大小,並且以前生成的索引可能會在有效範圍外結束。