ListenerList uses an internally-implemented linked list to enable concurrent modifications.

On Jul 2, 2009, at 3:37 AM, Noel Grandin wrote:


Good point.

I use CopyOnWriteArrayList to overcome the same problem.
Results in much less code, and since the bulk of listener lists are
typically very small (0-2 items), generally pretty cheap.

Regards, Noel.

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



Reply via email to