private static void initEventDispatcher() {
        if (dispatcher == null || !dispatcher.isAlive()) {
            dispatcher = new Thread("ClusterManager events dispatcher") {
                @Override
                public void run() {
                    // exit thread if/when clustering is disabled
                    while (ClusterManager.isClusteringEnabled()) {
                        try {
                            Event event = events.take();
                            EventType eventType = event.getType();
                            // Make sure that CacheFactory is getting this events first (to update cache structure)
                            if (event.getNodeID() == null) {
                                // Replace standalone caches with clustered caches and migrate data
                                if (eventType == EventType.joined_cluster) {
                                    CacheFactory.joinedCluster();
                                } else if (eventType == EventType.left_cluster) {
                                    CacheFactory.leftCluster();
                                }
                            }

                            // Now notify rest of the listeners
                            final List<ClusterEventListener> listenersOrderedBySequence = listeners
                                .stream()
                                .sorted(Comparator.comparing(Pair::getKey))
                                .map(Pair::getValue)
                                .collect(Collectors.toList());

                            for (ClusterEventListener listener : listenersOrderedBySequence) {
                                try {
                                    switch (eventType) {
                                        case joined_cluster: {
                                            if (event.getNodeID() == null) {
                                                listener.joinedCluster();
                                            }
                                            else {
                                                listener.joinedCluster(event.getNodeID());
                                            }
                                            break;
                                        }
                                        case left_cluster: {
                                            if (event.getNodeID() == null) {
                                                listener.leftCluster();
                                            }
                                            else {
                                                listener.leftCluster(event.getNodeID());
                                            }
                                            break;
                                        }
                                        case marked_senior_cluster_member: {
                                            listener.markedAsSeniorClusterMember();
                                            break;
                                        }
                                        default:
                                            break;
                                    }
                                }
                                catch (Exception e) {
                                    Log.error(e.getMessage(), e);
                                }
                            }
                            // Mark event as processed
                            event.setProcessed(true);
                        } catch (Exception e) {
                            Log.warn(e.getMessage(), e);
                        }
                    }
                }
            };
            dispatcher.setDaemon(true);
            dispatcher.start();
        }
    }
Instantiate and start the cluster event dispatcher thread
xmppserver/src/main/java/org/jivesoftware/openfire/cluster/ClusterManager.java