Event Listeners and Triggers in Java

There are a lot of mistakes I’ve seen people make when coding event listeners (and more commonly the classes that trigger events) in Java. One of the most common mistakes is:

List listeners = new ArrayList();

So whats the problem here? Well for one thing: ArrayList (like it says in the JavaDoc) is not synchronized, so it’s great for a single-thread environment. However, GUI’s are very often multi-threaded environments (unless you do everything on the EventDispatchThread, which is also a bad idea), so you may end up with a corrupt list of listeners.

Synchronization and threading issues are not massively likely in a GUI environment, but GUI applications are not the only ones with events, the problem can be solved in a few simple ways:

List listeners = new Vector();

or a more modern approach:

List listeners = Collections.synchronizedList(new ArrayList());

There is also the lovely javax.swing.EventListenerList which also happens to be a much more memory efficient solution. Bare in mind that it’s not bound to Swing in any way (other than the package it’s in). ArrayList and Vector both allocate memory for 10 entires when they are first initialized, whats more they grow exponentially in size. This is great if you are working with rapidly growing lists, but event listener lists tend to grow slowly and very seldom. EventListenerList lazy-creates it’s internal list, and so pre-allocates no “real” memory (space for a pointer, thats about it).

My preference for lists of event listeners is the java.util.concurrent.CopyOnWriteArrayList:

List<MouseListener> listeners = new CopyOnWriteArrayList<MouseListener>();

The CopyOnWriteArrayList is expensive to write to (add or remove), but wonderfully memory efficient, and inherently thread-safe. So unlike other List types, when firing an event off, you don’t have to synchronize on the List object, since if a write happens at the same time, the iterator you use points to a different array to the edited one.

MouseEvent e = new MouseEvent(...);
    for(MouseListener l : listeners) {
    l.mousePressed(e);
}

vs.

MouseEvent e = new MouseEvent(...):
synchronized(listeners) {
    for(MouseListener l : listeners) {
        l.mousePressed(e);
    }
}

One last note: When dealing with PropertyChangeListeners and Events (which is probably 60% of all events I work with), be sure to use a java.beans.PropertyChangeSupport to handle things for you.

Advertisements

3 Responses to “Event Listeners and Triggers in Java”

  1. idrishlaxmidhar Says:

    good article..
    wud like to visit again…
    ________
    “a newbie in tecnology….

  2. Mike Says:

    Your point about “javax.swing.EventListenerList… [is] not bound to Swing in any way other than the package it’s in” brings to mind a whole huge misconception about Jini in the early days (after we got past the “it’s about devices” crap.) Lots of people thought (still think) that its tied to RMI, simply because key interfaces defined in the Jini Specification extend java.rmi.Remote, and declare that (most) methods might throw RemoteException.

    Well, duh!? All they’re doing is declaring the semantics that “we may be far away in the network — expect failures” (See the “Eight Fallacies”) rather than (as most programmers seem to assume) “we’re tied to RMI’s mechanisms and are stuck with using RMI”.

    “Good News, Everyone!”…

  3. Willem Says:

    Thank you very much helped me a lot!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: