Lara
Lara

Reputation: 3174

Java Concurrency Issues concerning Listeners

What is the best, or the common solution to concurrency concerning Java? I see a lot of solutions on this and other websites, but none of them work for my problem.

My problem is as follows: I have a vector of a class I wrote myself. (If this helps solving it I can just as easily make it an ArrayList or something like that) Now, on a very regular basis (up to thousands of times per second) I read all elements in this vector and manipulate them in some way. At the same time I add and remove elements bases on events in my MouseListener and my KeyListener (which is essential to the program). This of course gives me quite a few problems. I don't want to read the vector while adding or removing elements, because this would throw a java.util.ConcurrentModificationException. However, I can't really use a temporary vector to store these events because that would create the problem of clearing this vector while adding things to it. How do you get out of this mess?

Upvotes: 3

Views: 111

Answers (2)

ggovan
ggovan

Reputation: 1927

You want to use a CopyOnWriteArrayList. This is safe to use in multithreaded and concurrent programming environments.

When iterating over a CopyOnWriteArrayList you will not get ConcurrentModificationExceptions as any changes create a new array internally and do not affect the one being iterated over. It was pretty much designed to host a list of listeners.

This has the benefit of not needing any synchronisation when iterating, and has very short locked segments, iteration will never block!

Upvotes: 1

Adam
Adam

Reputation: 36723

You can wrap your Vector of items with a thread safe wrapper using java.util.Collections. There is a specific method for List i.e. synchronizedList but not for Vector. This only solves part of the problem by synchronizing all the public method calls, add() and remove() etc.

private Collection<Thing> things =
         Collections.synchronizedCollection(new Vector<Thing>());

(or for a List)

private Collection<Thing> listeners =
       Collections.synchronizedList(new ArrayList<Thing>());

You also need to protect your iteration... There are two ways to do this, either lock the collection whilst you iterate...

synchronized (things) {
    for (Thing thing : things) {

    }
}

or take a copy and iterate over that...

for (Thing thing : things.toArray(new MouseListener[]{})) {

}

Upvotes: 3

Related Questions