Reputation: 3174
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
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 ConcurrentModificationException
s 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
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