Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

ListenerList - a Better Way to Manage Your Event Listeners

DZone's Guide to

ListenerList - a Better Way to Manage Your Event Listeners

· Java Zone
Free Resource

Just released, a free O’Reilly book on Reactive Microsystems: The Evolution of Microservices at Scale. Brought to you in partnership with Lightbend.

You have published a listener interface and have a place where your clients register their listeners. There you typically code like this:

List<SomeEventListener> listeners = new ArrayList<SomeEventListener>(); 

public void addSomeEventListener(SomeEventListener listener) { 
    listeners.add(listener); 
} 

public void removeSomeEventListener(SomeEventListener listener) { 
    listeners.remove(listener); 
} 

public void fireSomeEvent(SomeEvent event) { 
    for (SomeEventListener listener : listeners) { 
        listener.eventOccured(event); 
    } 
}

The problem with this approach is two fold:

  1. Memory usage: The capacity of the ArrayList is always >= its size. So if you just have 200 listeners, there is a good chance that the memory might have been allocated for 300 elements
  2. Thread safety: Murphy's law will prove itself, and multi threaded bugs can be a pain in your back to debug. You have to properly sync all the write access and provide faster read only access for event firing operations.

To handle these two issues, Eclipse gives you a nice API: ListenerList class. Its meant for storing these kind of listeners, where any write modification to the underlying array (add, remove, clear) is synchronized and give access to the underlying array for faster read access. Memory is allocated only for the number of listeners registered.

The same above example can be rewritten as:

ListenerList listeners = new ListenerList(); 

public void addSomeEventListener(SomeEventListener listener) { 
    listeners.add(listener); 
} 

public void removeSomeEventListener(SomeEventListener listener) { 
    listeners.remove(listener); 
} 

public void fireSomeEvent(SomeEvent event) { 
    Object[] listenersArray = listeners.getListeners(); 
    for (int i = 0; i < listenersArray.length; i++) { 
        ((SomeEventListener)listenersArray[i]).eventOccured(event); 
    } 
}

 

ListenerList provides two ways of duplicate checking of the listeners: Equality and Identity. It can be specified in the constructor. Since the core Eclipse platform is in Java 1.4, you still can't use generics and foreach, but that shouldn't be a hindrance.

Question: Now that I do have a direct access to the underlying array, what if i manipulate it like this:

Object[] listenersArray = listeners.getListeners(); 
listenersArray[0] = null; 
listenersArray[1] = someEventListener5;

 

Well, the same thing happens when you shoot yourself in the foot :-)

 

Strategies and techniques for building scalable and resilient microservices to refactor a monolithic application step-by-step, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}