private void verifyStatsAfterExpiration(int numOfEvents) {
    HARegionQueueStats stats = getCacheClientProxy().getHARegionQueue().getStatistics();

    long actualEventsExpired = stats.getEventsExpired();
    long expectedEventsExpired = isPrimaryServer() ? 0 : numOfEvents;

    assertThat(actualEventsExpired)
        .as("Expected eventsExpired: " + expectedEventsExpired + " but actual eventsExpired: "
            + actualEventsExpired + (isPrimaryServer() ? " at primary." : " at secondary."))
        .isEqualTo(expectedEventsExpired);

    int actualThreadIds = stats.getThreadIdentiferCount();

    // Sometimes we may see 1 threadIdentifier due to slow machines, but never equal to
    // expectedThreadIds
    assertThat(actualThreadIds).as("Expected ThreadIdentifier count <= 1 but actual: "
        + actualThreadIds + (isPrimaryServer() ? " at primary." : " at secondary.")).isEqualTo(0);
  }
HARegionQueueThreadIdExpiryRegressionTest
<p>
TRAC #48879: Leaking ThreadIdentifiers and DispatchedAndCurrentEvents objects when client uses
many short lived threads
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/ha/HARegionQueueThreadIdExpiryRegressionTest.java