具有共享ArrayList的并发修改异常

时间:2013-07-26 19:41:58

标签: java concurrency arraylist

我正在制作一个程序,模拟派对中的字符,检查/输出属于整个派对的ArrayList所需的工件。在我的生物将他们的物品放入聚会ArrayList然后遍历它寻找正确的工件后,我得到了一个并发修改异常。

这就是我的流程:最初所有角色都是使用随机的Artifacts创建的。执行作业时,它将检查它是否具有正确数量的工件。如果确实如此,它将完成这项工作,并将其拥有的所有工件发布到各方ArrayList中。如果没有,那么它将等待机会使用各方ArrayList,并且当它有机会将其所有项目放入其中并迭代以获得正确的项目。

注意:一次只有一个生物可以与各方ArrayList互动

这是我的代码位于线程本身,以确保所有线程合作:

 boolean ready = target.hasReqArtifacts( reqStones, reqPotions, reqWands, reqWeapons );
    //checks to see if creature already has correct amount of each item
    while ( !ready ) {//begin pool interaction
        synchronized ( target.poolParty ){
            while ( target.poolParty.busyPool ) {//busyPool is initialized false
                startJob.setEnabled( false );
                startJob.setText( "Waiting for Pool");
                try {
                    target.wait();
                } catch ( InterruptedException e ) {}
            }
            synchronized ( target.poolParty ) {
                target.poolParty.busyPool = true;
                target.poolParty.notifyAll();//notify all threads that they need to wait because this one will proceed
            }
        }
        target.releaseArtifacts();// adds all artifacts held by creature to an arraylist in poolParty
                                  //then clears the creatures inventory
        target.pickUpArtifacts( reqStones, reqPotions, reqWands, reqWeapons );
        //Searches through poolParty's ArrayList of artifacts for required artifacts

        ready = target.hasReqArtifacts( reqStones, reqPotions, reqWands, reqWeapons );
        if ( ready ) {
            synchronized ( target.poolParty ) {
                target.poolParty.busyPool = false;
                target.poolParty.notify();
            }
        } else {
            synchronized ( target.poolParty ) {
                target.poolParty.busyPool = false;
                target.releaseArtifacts();
                target.poolParty.notify();
            }
        }
    }//end pool interaction

在调用“releaseArtifacts”后调用“pickUpArtifacts”方法时代码中断了 下面是我的方法pickUpArtifacts:

public void pickUpArtifacts ( int stones, int potions, int wands, int weapons ){
    hasReqArtifacts( stones, potions, wands, weapons );
    String                              theType;

    if ( !poolParty.resourcePool.isEmpty() ) {//itterate through whole pool to see if it can get needed items
        for ( Artifact a : poolParty.resourcePool ) {//This is where the code breaks
            theType =                     a.getType();
            if ( theType.equals( "Stone" ) && ( curStones < stones )) {
                addArtifact( a );
                poolParty.resourcePool.remove( a );
            } else if ( theType.equals( "Potion" ) &&  ( curPotions < potions ) ) {
                addArtifact( a );
                poolParty.resourcePool.remove( a );
            } else if ( theType.equals( "Wand" ) && ( curWands < wands )) {
                addArtifact( a );
                poolParty.resourcePool.remove( a );
            } else if ( theType.equals( "Weapon" ) && ( curWeapons < weapons )) {
                addArtifact( a );
                poolParty.resourcePool.remove( a );
            }
        }
    }
    hasReqArtifacts( stones, potions, wands, weapons );
}

最初我使用锁来尝试同步。这最终导致了同样的错误,所以我使用类似于我用来杀死线程的布尔标志的同步代码来接近它。在那之后不起作用我精确地调整了代码执行的位置,以便在迭代期间不会操纵ArrayList。

它继续抛出与以前相同的错误。它甚至在同一过程中崩溃。我似乎无法弄清楚什么是错的。

2 个答案:

答案 0 :(得分:2)

迭代时不能修改集合。在这种情况下,它与多个线程无关。

请注意,您正在迭代这个集合

for ( Artifact a : poolParty.resourcePool )

然后,在for块中,您尝试从同一个集合中删除

poolParty.resourcePool.remove( a );

要在这种情况下有效地从列表中删除,请使用Iterator和迭代器remove方法。

答案 1 :(得分:-1)

创建列表时,您应该使用下一个代码,

List yourList = Collections.synchronizedList(new ArrayList())

(在同步块/方法内)