0

我正在制作一个程序来模拟派对中的角色签入/签出他们需要的工件,这些工件来自属于整个派对的 ArrayList 的工作。在我的生物将他们的物品放入各方 ArrayList 中,然后遍历它以寻找正确的工件后,我得到了一个并发修改异常。

这就是我的流程:最初,所有角色都是用随机的各种人工制品创建的。在执行一项工作时,它会检查它是否有正确数量的 Artifact。如果这样做,它将完成这项工作,并将它拥有的所有工件释放到各方 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。

它继续抛出与以前相同的错误。它甚至在同一过程中分解。我似乎无法弄清楚出了什么问题。

4

2 回答 2

2

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

请注意,您在这里迭代集合

for ( Artifact a : poolParty.resourcePool )

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

poolParty.resourcePool.remove( a );

在这种情况下,要有效地从 List 中删除,请使用Iterator和 Iteratorsremove方法。

于 2013-07-26T19:54:55.753 回答
-1

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

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

(在同步块/方法内)

于 2013-07-26T19:46:21.180 回答