@Override
  public void init(Services<ID> s) throws MembershipConfigurationException {
    services = s;

    MembershipConfig config = services.getConfig();
    if (config.getMcastPort() != 0 && StringUtils.isBlank(config.getLocators())
        && StringUtils.isBlank(config.getStartLocator())) {
      throw new MembershipConfigurationException(
          "Multicast cannot be configured for a non-distributed cache."
              + "  Please configure the locator services for this cache using "
              + MembershipConfig.LOCATORS + " or "
              + MembershipConfig.START_LOCATOR + ".");
    }

    services.getMessenger().addHandler(JoinRequestMessage.class, this::processJoinRequestMessage);
    services.getMessenger().addHandler(JoinResponseMessage.class, this::processJoinResponseMessage);
    services.getMessenger().addHandler(InstallViewMessage.class, this::processInstallViewMessage);
    services.getMessenger().addHandler(ViewAckMessage.class, this::processViewAckMessage);
    services.getMessenger().addHandler(LeaveRequestMessage.class, this::processLeaveRequestMessage);
    services.getMessenger().addHandler(RemoveMemberMessage.class, this::processRemoveMemberMessage);
    services.getMessenger().addHandler(FindCoordinatorRequest.class,
        this::processFindCoordinatorRequestMessage);
    services.getMessenger().addHandler(FindCoordinatorResponse.class,
        this::processFindCoordinatorResponseMessage);
    services.getMessenger().addHandler(NetworkPartitionMessage.class,
        this::processNetworkPartitionMessage);

    long ackCollectionTimeout = config.getMemberTimeout() * 2 * 12437 / 10000;
    if (ackCollectionTimeout < 1500) {
      ackCollectionTimeout = 1500;
    } else if (ackCollectionTimeout > 12437) {
      ackCollectionTimeout = 12437;
    }

    viewAckTimeout = ackCollectionTimeout;

    quorumRequired =
        config.isNetworkPartitionDetectionEnabled();

    String bindAddr = config.getBindAddress();
    locators = LocatorConfigurationParser.parseLocators(config.getLocators(), bindAddr);
    if (logger.isDebugEnabled()) {
      logger.debug("Parsed locators are {}", locators);
    }
  }
True iff the weight of "crashed" members in the new view is
greater-than-or-equal-to half of the weight of all members in
the old (current) view.

For this discussion "crashed" members are members for which the
coordinator has received a RemoveMemberRequest message. These
are members that the failure detector has deemed failed.
Keep in mind the failure detector is imperfect (it's not always
right). We may have merely lost contact with a "failed" member,
but that doesn't mean it can't still be running
(on the other side of a network partition).

Callers use a true result from this method to cause the
coordinator (this member) to force-disconnect rather than
continue with the view change.

If you think about a general N-way network partition for N=2,
3...M where M is the number of members in the current view,
requiring any coordinator producing a new view, to ensure
that weight of possibly-but-not-certainly-crashed members in
the new view to be less than half the weight of members in the
old view, ensures that the view change never results in a split-
brain.
geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java