The ListenerList class is actually designed to handle concurrent
modifications gracefully (so listeners can remove themselves from a
listener list during an event, if necessary). As a result, a CME will
never be thrown.
Note that ListenerList is not designed to be thread-safe. Most events
are fired by UI constructs on the event dispatch thread, so the
overhead of synchronization is not justified (or desired). If you need
thread-safe access to the list, you can create a synchronized subclass
- see
org
.apache
.pivot
.collections
.synchronized.SynchronizedList.SynchronizedListListenerList for an
example.
On Jul 2, 2009, at 3:14 AM, Niclas Hedhman wrote:
Guys,
I am looking at the implementation of listeners, a topic I think I am
pretty good at.
AFAICT, you have exposed yourself to intermittent
ConcurrentModificationExceptions since the event firing and listener
list modifications are against the same list. If a new listener is
added/removed while the events are being fired/handled, it seems that
CME will be thrown.
To overcome this, I normally use the following pattern;
public void addAbcListener( AbcListener listener )
{
ArrayList listeners = new ArrayList();
listeners.putAll( this.abcListeners );
listeners.add( listener );
synchronized( this )
{
this.abcListeners = listeners;
}
}
public void fireEvent( ... )
{
Iterator it;
synchronized( this )
{
it = abcListeners.iterator();
}
while( it.hasNext() )
{
AbcListener listener = it.next();
try
{
listener.someMethod( ... );
} catch( Excption e )
{
// delegate caught exception to some system.
}
}
}
This ensures that CME won't happen, as the Iterator is not backed by
the List where the modifications are occurring. If synchronized is
considered too expensive, I think it would also work if the
this.abcListener is volatile, but that is not verified.
Cheers
--
Niclas Hedhman, Software Developer
http://www.qi4j.org - New Energy for Java
I live here; http://tinyurl.com/2qq9er
I work here; http://tinyurl.com/2ymelc
I relax here; http://tinyurl.com/2cgsug