Thank you Patricia for the excellent response.
variable to make the code faster. I'll move it back being a local
variable.
Daisy wrote:
I'm getting a java.util.NoSuchElementException at high loads using
java.util.concurrent.CopyOnWriteArraySet. I have one guess why and
would like to hear if it makes sense. Could this error occur because
two threads call the same instance?
For example, thread A executes i.hasNext() which returns true. Then
thread B runs and happens to start executing at i.next(). When thread
A runs again, it will execute the i.next() but B has already advanced
the iterator to the end of the list.
I'm using CopyOnWriteArraySet to avoid synchronizing. Do I have to
sync to avoid this issue?
Thanks for the opinions!
public class DistributionSet extends CopyOnWriteArraySet {
private Iterator i;
public void enqueue( Object message ) {
for ( i = this.iterator( ) ; i.hasNext( ) ; ) {
// .next() call is throwing an error - why? either:
// copy hasn't completed or .hasNext() has a different
count, or some listener was removed
EventListener listener = ( EventListener ) i.next( );
listener.eventObserved( message ) ;
}
}
public boolean add( EventListener consumer ) {
super.add( consumer );
return true;
}
}
If enqueue can be called in multiple threads, then there is a risk of
NoSuchElementException. For example:
Suppose thread A calls enqueue, and enqueue assigns to i the Iterator
reference iterator() returned, and i.hasNext() returns true. Now A gets
interrupted, thread B starts running, and thread B calls enqueue.
Thread B assigns to i the Iterator reference that its iterator() call
returned. At that point, the thread A Iterator becomes unreachable.
Thread B completes its enqueue call, leaving i referencing an iterator
that returned false from i.hasNext().
Now thread A gets control back, but i references the Iterator that
thread B was using. The thread A next call fails.
If the uses of the shared Iterator are finely interleaved, as they could
be on a dual processor, you could get other problems such as not passing
a particular message to some listeners.
However, it is a problem you created, by choosing to make i an instance
field forcing multiple threads to share the iterator reference. Why is
that necessary?
If i were local, each enqueue activation would be able to remember its
own Iterator reference.
Patricia