public void publish(Object event) { if (event == null) { log.info("Received null event for publishing. Ignoring and returning."); return; } registryReadLock.lock(); try { //performing the entire iteration within the lock will be a slow operation if the registry has a lot of //contention. However, it is expected that the very large majority of cases the registry will be //read-mostly with very little writes (registrations or removals) occurring during a typical application //lifetime. // //The alternative would be to copy the registry.values() collection to a new LinkedHashSet within the lock //only and the iteration on this new collection could be outside the lock. This has the performance penalty //however of always creating a new collection every time an event is published, which could be more //costly for the majority of applications, especially if the number of listeners is large. // //Finally, the read lock is re-entrant, so multiple publish calls will be //concurrent without penalty since publishing is a read-only operation on the registry. for (Subscription subscription : this.registry.values()) { subscription.onEvent(event); } } finally { registryReadLock.unlock(); } }
public void register(Object instance) { if (instance == null) { log.info("Received null instance for event listener registration. Ignoring registration request."); return; } unregister(instance); List<EventListener> listeners = getEventListenerResolver().getEventListeners(instance); if (listeners == null || listeners.isEmpty()) { log.warn("Unable to resolve event listeners for subscriber instance [{}]. Ignoring registration request.", instance); return; } Subscription subscription = new Subscription(listeners); this.registryWriteLock.lock(); try { this.registry.put(instance, subscription); } finally { this.registryWriteLock.unlock(); } }