@Override
      public void run() {
         synchronized(listenerLock) {
            ThreadSafeEventService.this.publish(new CleanupEvent(CleanupEvent.Status.STARTING, weakRefPlusProxySubscriberCount, null));
            if (weakRefPlusProxySubscriberCount <= cleanupStopThreshold) {
               this.cancel();
               cleanupTimer = null;
               cleanupTimerTask = null;
               LOG.debug("Cancelled scheduled weak reference and proxy cleanup.");
               ThreadSafeEventService.this.publish(new CleanupEvent(CleanupEvent.Status.UNDER_STOP_THRESHOLD_CLEANING_CANCELLED, weakRefPlusProxySubscriberCount, null));
               return;
            }
            LOG.debug("Starting a weak reference and proxy cleanup.");
            ThreadSafeEventService.this.publish(new CleanupEvent(CleanupEvent.Status.OVER_STOP_THRESHOLD_CLEANING_BEGUN, weakRefPlusProxySubscriberCount, null));               
            List<Map> allSubscriberMaps = new ArrayList<Map>();
            allSubscriberMaps.add(subscribersByEventType);
            allSubscriberMaps.add(subscribersByEventClass);
            allSubscriberMaps.add(subscribersByExactEventClass);
            allSubscriberMaps.add(subscribersByTopic);
            allSubscriberMaps.add(subscribersByTopicPattern);
            allSubscriberMaps.add(vetoListenersByClass);
            allSubscriberMaps.add(vetoListenersByExactClass);
            allSubscriberMaps.add(vetoListenersByTopic);
            allSubscriberMaps.add(vetoListenersByTopicPattern);
            
            int staleCount = 0;
            for (Map subscriberMap : allSubscriberMaps) {
               Set subscriptions = subscriberMap.keySet();
               for (Object subscription : subscriptions) {
                  List subscribers = (List) subscriberMap.get(subscription);
                  for (Iterator iter = subscribers.iterator(); iter.hasNext();) {
                     Object subscriber = iter.next();
                     Object realSubscriber = getRealSubscriberAndCleanStaleSubscriberIfNecessary(iter, subscriber);                      
                     if (realSubscriber == null) {
                        staleCount++;
                     }
                  }
               }
            }
            ThreadSafeEventService.this.publish(new CleanupEvent(CleanupEvent.Status.FINISHED_CLEANING, weakRefPlusProxySubscriberCount, staleCount));
         }         
      }