2014-12-02 207 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的原因的情况。

正如在评论中已经说过的那样,错误的原因是:玩家指数是在初始列表中生成的,并且在那时它们确实是有效的。删除循环会减小列表大小,并且以前生成的索引可能会在有效范围外结束。