protected void internalCallStatListeners(long timestamp, int[] listenerIds, double[] values) {
    ListenerIdMap.Entry[] entries = null;
    List listenersToRemove = new ArrayList();
    synchronized (statListenersLock) {
      entries = statListeners.entries();
    }

    for (final ListenerIdMap.Entry entry : entries) {
      int listenerId = entry.getKey();
      StatListener sl = (StatListener) entry.getValue();
      int i;
      for (i = 0; i < listenerIds.length; i++) {
        if (listenerIds[i] == listenerId || listenerIds[i] == -listenerId) {
          break;
        }
      }
      if (i == listenerIds.length) {
        sl.statValueUnchanged(timestamp);
      } else if (listenerIds[i] < 0) { // Stat resource went away
        listenersToRemove.add(listenerId);
      } else {
        sl.statValueChanged(values[i], timestamp);
      }
    }

    synchronized (statListenersLock) {
      for (final Object o : listenersToRemove) {
        int i = (Integer) o;
        statListeners.remove(i);
        cancelStatListener(i);
      }
    }
  }
Invokes the callback methods on a bunch of <code>StatListener</code>s in response to a
statistics update message being received. This method is invoked in its own thread.

for each listener in statListeners call stat value changed if its id is in listenerIds call
stat value unchanged if its id is not in listenerIds call cancelStatListener and
statListeners.remove if its id is negative in listenerIds

@see #cancelStatListener
geode-core/src/main/java/org/apache/geode/internal/admin/remote/RemoteGemFireVM.java