Related:
Does java have a "LinkedConcurrentHashMap" data structure?
I am looking for a collection class to hold references to event listeners.
Ideally I would like the collection to have the following properties (in order of priority):
- Maintains insertion order. The earlier listeners may cancel the event, preventing it from being delivered to listeners added later. This will break if using a class such as
HashSetwhose iterator may return elements in the wrong order. - Uses
WeakReferences so that the listener list does not prevent the listeners from being garbage-collected. - The collection is a
Set, so duplicates are automatically removed. - The
Iteratoris a thread-safe snapshot of the collection, unaffected by the addition of new listeners. Also allows events to be delivered on multiple threads. (This is not essential – I could iterate over a clone of the set instead.)
I am aware of some classes that satisfy some but not all of these criteria. Examples:
java.util.LinkedHashSet(#1 and #3)java.util.WeakHashMap, wrapped byCollections.newSetFromMap(#2 and #3)javax.swing.event.EventListenerList(needs some extra synchronization) (#1 and #4)java.util.concurrent.CopyOnWriteArraySet(#1, #3 and #4)
But nothing with both #1 and #2. Does class like this exist in a library somewhere?
You could use WeakListeners (see http://bits.netbeans.org/dev/javadoc/org-openide-util/org/openide/util/WeakListeners.html) and CopyOnWriteArraySet.
remove(ListenerType listener)method in your event source.In your
register(SomeListener listener)method, add a WeakListener to the collection instead:listenerCollection.put((ListenerType)WeakListeners.create (ListenerType.class, listener, this));
When the real listener is removed from memory, the weak listener will be notified, and it will unregister itself. (This is why it needs the reference to the source (
this) for the registration.) The unregistration is done using reflection by calling the method remove of the source.