1

I am still at an early stage of developing a game in Android (in Java) and I have run into a Concurrency issue with adding/removing Objects from my Game loop.

The application has 2 separate fragments, one which is a controller and the other is the SurfaceView displaying the Game loop. The controller has buttons which prompts the creation of Objects which are then added to the Game loop. The Concurrency issue pops up seemingly randomly, but mostly when an Object is removed from the ArrayList storing it and another is being added to it to be drawn.

The crashes do not happen uniformly or at the same points during running so I am at a loss here. I have already switched all my For-each loops over to ListIterator add/remove calls thinking it would stave off the Concurrency problems but it has proven to be ineffective.

Am I going to have to employ locking with my Object adds until after the next completion of draw() or is there another way?

Thanks in advance.

Edit:

// Adds new Objects to ArrayList
ListIterator<Projectile> iterator = curr_player.getProjectiles().listIterator();
iterator.add(new_p);

// Code to remove Object when it goes off View Boundaries
public boolean projectileBoundary()
{
    Projectile p;
    for (ListIterator<Projectile> iterator = curr_player.getProjectiles().listIterator(); iterator.hasNext();)
    {
        p = iterator.next();
        if (p.getX() > p.getXMax())
        {
            iterator.remove();
            return true;
        }

    }

    return false;

}

// Objects drawn to canvas using this function
public void drawProjectiles()
{
    for (Iterator<Projectile> iterator = curr_player.getProjectiles().iterator(); iterator.hasNext();)
    {
        Projectile p = iterator.next();
        drawProjectile(p);
    }

}

As was previously stated the application does NOT crash only when removing it happens before deletions ever occur. Which indicates there is a problem updating the ArrayList that is being drawn with the new Objects being added to it concurrently.

The application terminates in the error: java.util.ConcurrentModificationException at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)

Brendan M
  • 11
  • 3
  • 4
    *single thread concurrency*? – Gurwinder Singh Dec 28 '16 at 15:53
  • 1
    Did you bother to read what I wrote or just the title? – Brendan M Dec 28 '16 at 16:00
  • Please post some relevant code. Also, as asked above, if you have only one thread then you can not have concurrency issues. – Okas Dec 28 '16 at 16:52
  • The code throws the error "java.util.ConcurrentModificationException at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)" due to add/remove operations happening at the same time. If that is not Concurrency perhaps I am missing something. I will include some code. – Brendan M Dec 28 '16 at 17:16
  • A ConcurrentModificationException is *NOT* necessarily a concurrency issue. It simply means that the contents of a collection changed, while an iterator was iterating over it. No concurrency need be involved. – G. Blake Meike Dec 28 '16 at 17:48
  • This would be *SO* *MUCH* easier to figure out if you included the actual stack trace, and the code at line 573. – G. Blake Meike Dec 28 '16 at 17:51
  • @G.BlakeMeike Yeah you're right, I figured this was the problem and was looking for direction. – Brendan M Dec 28 '16 at 17:52
  • I cannot include that line of code since it is not in my program... that is thrown by the ArrayList class... – Brendan M Dec 28 '16 at 17:53

2 Answers2

0

If it is concurrency problem then use thread-safe data structure. Use CopyOnWriteArrayList instead of ArrayList. CopyOnWriteArrayList is thread-safe

  • My only concern with this would be the large amount of refactoring that this List will do in possibly a single iteration of the Game loop. At what size of the CopyOnWriteArrayList does the performance begin to become terrible? – Brendan M Dec 28 '16 at 16:10
  • As it is tread-safe ofcourse it is a costly operation. Please follow thee link : http://stackoverflow.com/questions/17853112/in-what-situations-is-the-copyonwritearraylist-suitable – MdFazlaRabbiOpu Dec 28 '16 at 16:18
0

Rather than implement the CopyOnWriteArrayList, I cannot justify taking that kind of performance hit, I simply implemented an ArrayList that serves as a buffer for all Objects that will simply be added next Iteration. The idea is as follows:

// Buffer for adding to Projectiles
ListIterator<Projectile> iterator = temp_buffer.listIterator();
iterator.add(new_p);

Then I attach the temp_buffer before the next update() to my canvas using:

// Updating Projectiles on Canvas
public void updateProjectiles()
{
    // Add temp_buffer to Projectile List
    curr_player.getProjectiles().addAll(temp_buffer);

    for (Iterator<Projectile> iterator = curr_player.getProjectiles().iterator(); iterator.hasNext();)
    {
        Projectile p = iterator.next();
        p.update();
    }

    temp_buffer.removeAll(temp_buffer);

}

This successfully solved all of the problems I had associated with the java.util.ConcurrentModificationException.

Brendan M
  • 11
  • 3