public void fireThreadCleanup() { // Here's where we need the CursorableLinkedList since listeners // are free to unregister as listeners from threadDidCleanup() and // we need to avoid concurrent modification errors. EventListenerList list = (EventListenerList) _storage.get(); if (list == null) return; Iterator i = list.getListeners(); // Discard the list of listeners as early as possible to ensure that // they can in no way be retained, even if this thread aborts abnormally. _storage.set(null); while (i.hasNext()) { ThreadCleanupListener listener = (ThreadCleanupListener) i.next(); // Each listener may decide to remove itself; that's OK, // EventListenerList handles that kind of concurrent modification // well. try { listener.threadDidCleanup(); } catch (RuntimeException ex) { _log.warn(ServiceMessages.threadCleanupException(ex), ex); } } }