0

I'm making a program that simulates characters in a party checking in / out Artifacts they require for jobs from an ArrayList that belongs to the whole party. After my creatures drop their items into the parties ArrayList and then iterate through it looking for the correct Artifacts I get a Concurrent Modification exception.

This is how I have it flow: Initially all characters are created with a random assortment of Artifacts. When performing a job it will check if it has the correct amount of Artifact. If it does it will do the job, and release all the artifacts it has into the parties ArrayList. If it does not it will then wait for a chance to use the parties ArrayList and when given the chance it will drop all its items into it and iterate through for the correct Items.

Note: only one creature may interact with the parties ArrayList at a time

This is my code located in the thread itself for making sure all the the threads cooperate:

 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

The code breaks when I call the "pickUpArtifacts" method after calling "releaseArtifacts" Below is my method 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 );
}

Initially I was using attempting synchronization using locks. This ended up throwing the same error so I approached it with synchronized code with boolean flags similar to what I use for killing the thread. After that did not work I fine tuned exactly where the code was performing so that nothing would manipulate the ArrayList during iteration.

It continues to throw the same error as before. It even breaks down during the same process. I cant seem to figure out whats wrong.

1
  • 1
    You're modifying a List while iterating over it. That's exactly what should happen. Use an iterator and its methods. Commented Jul 26, 2013 at 19:46

2 Answers 2

2

You cannot modify a collection while iterating over it. In this case it has nothing to do with multiple threads.

Notice you are iterating over the collection here

for ( Artifact a : poolParty.resourcePool )

Then, inside the for block, you try to remove from the same collection

poolParty.resourcePool.remove( a );

To effectively remove from a List in this case, use an Iterator and the Iterators remove method.

Sign up to request clarification or add additional context in comments.

Comments

-1

You should probably use the next code, when creating a list,

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

(inside a synchronized block/method)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.