Let's begin with a quick review of listener notification, which is in fact just another name for event delivery. Event delivery is in turn fully described in Section 6.6 of the JavaBeans 1.01 specification (see Resources).
When a JavaBean wants to trigger an event, it notifies all registered listeners by calling the event's method on the registered
listeners' listener interfaces. Listeners register with a JavaBean by calling the bean's add<ListenerType>(<ListenerType> listener)method.
Section 6.5.1 of the JavaBeans 1.01 specification contains an example of event-listener registration and event-listener notification. The source code from this example forms the basis of my analysis:
public interface ModelChangedListener extends
java.util.EventListener
{
void modelChanged(EventObject e);
}
public abstract class Model {
private Vector listeners = new Vector(); // list of Listeners
public synchronized void
addModelChangedListener(ModelChangedListener mcl) {
listeners.addElement(mcl);
}
public synchronized void
removeModelChangedListener(ModelChangedListener mcl) {
listeners.removeElement(mcl);
}
protected void notifyModelChanged() {
Vector l;
EventObject e = new EventObject(this);
// Must copy the Vector here in order to freeze the state of the
// set of EventListeners the event should be delivered to prior
// to delivery. This ensures that any changes made to the Vector
// from a target listener's method, during the delivery of this
// event will not take effect until after the event is delivered
synchronized(this) { l = (Vector)listeners.clone(); }
for (int i = 0; i < l.size(); i++) { // deliver it!
((ModelChangedListener)l.elementAt(i)).modelChanged(e);
}
}
}The JavaBeans 1.01 specification specifically states that the list of listeners can potentially be updated at the same time that those very listeners are being notified of events. The target listener may modify the listener list, or a different thread may attempt to add or remove listeners.
Thus, the JavaBeans 1.01 specification allows for different implementations. An implementation can make a copy of the list of listeners, and then notify only the listeners in the copied list of events; alternately, an implementation can use the current (and potentially changing) list as it proceeds with the notifications. Using a copy means that additions and removals that take place during the notification process do not alter the list of listeners being notified of the current event. Notice that the example above uses just such a copy implementation.