3

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?

Lara
  • 2,594
  • 4
  • 24
  • 36

2 Answers2

3

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[]{})) {

}
Adam
  • 35,919
  • 9
  • 100
  • 137
  • You misunderstood me, this does not concern a vector of listeners. It's about `add` and `remove` called by listeners. Anyhow, this provided some useful info so I'll see if it helps. Downvote was not me by the way :P – Lara Feb 01 '15 at 20:07
  • Thanks, updated my answer... principles are still exactly the same, I do a lot of GUI stuff, so wrongly assumed. – Adam Feb 01 '15 at 20:10
  • Also, if you could provide the answer for just a list that would be appreciated (though I think I'll be able to do it myself, so if not: no problem). I used the vector to fix some issue I do not have anymore anyways. – Lara Feb 01 '15 at 20:12
  • Add List example to question, everything else is same after the initial construction... – Adam Feb 01 '15 at 20:14
  • Oh lol, I didn't realise hardly anything would change :P Thx! – Lara Feb 01 '15 at 20:16
  • `Vector` already has all its operations synchronised, making a synchronised collection of it is pointless. – ggovan Feb 01 '15 at 22:46
1

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!

ggovan
  • 1,907
  • 18
  • 21