@Test
  public void testConcurrentDispatcherAndRemovalForMultipleRegionsDifferentThreadId()
      throws Exception {
    int numberOfIterations = 1000;
    HARegionQueue hrq1 = createHARegionQueue(testName.getMethodName() + "-1");
    HARegionQueue hrq2 = createHARegionQueue(testName.getMethodName() + "-2");
    HARegionQueue hrq3 = createHARegionQueue(testName.getMethodName() + "-3");
    HARegionQueue hrq4 = createHARegionQueue(testName.getMethodName() + "-4");
    HARegionQueue hrq5 = createHARegionQueue(testName.getMethodName() + "-5");

    HARegionQueue.stopQRMThread();

    ThreadIdentifier[] ids1 = new ThreadIdentifier[(int) numberOfIterations];
    ThreadIdentifier[] ids2 = new ThreadIdentifier[(int) numberOfIterations];
    ThreadIdentifier[] ids3 = new ThreadIdentifier[(int) numberOfIterations];
    ThreadIdentifier[] ids4 = new ThreadIdentifier[(int) numberOfIterations];
    ThreadIdentifier[] ids5 = new ThreadIdentifier[(int) numberOfIterations];

    for (int i = 0; i < numberOfIterations; i++) {
      ids1[i] = new ThreadIdentifier(new byte[] {1}, i);
      ids2[i] = new ThreadIdentifier(new byte[] {2}, i);
      ids3[i] = new ThreadIdentifier(new byte[] {3}, i);
      ids4[i] = new ThreadIdentifier(new byte[] {4}, i);
      ids5[i] = new ThreadIdentifier(new byte[] {5}, i);
      hrq1.addDispatchedMessage(ids1[i], i);
      hrq2.addDispatchedMessage(ids2[i], i);
      hrq3.addDispatchedMessage(ids3[i], i);
      hrq4.addDispatchedMessage(ids4[i], i);
      hrq5.addDispatchedMessage(ids5[i], i);
    }

    Thread thread1 = new Thread() {
      @Override
      public void run() {
        try {
          Thread.sleep(600);
        } catch (InterruptedException e) {
          errorCollector.addError(e);
        }
        list1 = HARegionQueue.createMessageListForTesting();
      }
    };

    Thread thread2 = new Thread() {
      @Override
      public void run() {
        try {
          Thread.sleep(480);
        } catch (InterruptedException e) {
          errorCollector.addError(e);
        }
        for (int i = 0; i < numberOfIterations; i++) {
          ids1[i] = new ThreadIdentifier(new byte[] {1}, i + numberOfIterations);
          ids2[i] = new ThreadIdentifier(new byte[] {2}, i + numberOfIterations);
          ids3[i] = new ThreadIdentifier(new byte[] {3}, i + numberOfIterations);
          ids4[i] = new ThreadIdentifier(new byte[] {4}, i + numberOfIterations);
          ids5[i] = new ThreadIdentifier(new byte[] {5}, i + numberOfIterations);

          hrq1.addDispatchedMessage(ids1[i], i + numberOfIterations);
          hrq2.addDispatchedMessage(ids2[i], i + numberOfIterations);
          hrq3.addDispatchedMessage(ids3[i], i + numberOfIterations);
          hrq4.addDispatchedMessage(ids4[i], i + numberOfIterations);
          hrq5.addDispatchedMessage(ids5[i], i + numberOfIterations);
        }
      }
    };

    thread1.start();
    thread2.start();
    ThreadUtils.join(thread1, 30 * 1000);
    ThreadUtils.join(thread2, 30 * 1000);
    List list2 = HARegionQueue.createMessageListForTesting();
    Iterator iterator = list1.iterator();
    boolean doOnce = true;
    EventID id = null;
    Map map = new HashMap();

    while (iterator.hasNext()) {
      if (!doOnce) {
        iterator.next(); // read the total message size
        doOnce = true;
      } else {
        iterator.next(); // region name;
        int size = (Integer) iterator.next();
        System.out.println(" size of list 1 iteration x " + size);
        for (int i = 0; i < size; i++) {
          id = (EventID) iterator.next();
          map.put(new ThreadIdentifier(id.getMembershipID(), id.getThreadID()), id.getSequenceID());
        }
      }
    }

    iterator = list2.iterator();
    doOnce = true;

    while (iterator.hasNext()) {
      if (!doOnce) {
        iterator.next(); // read the total message size
        doOnce = true;
      } else {
        iterator.next(); // region name;
        int size = (Integer) iterator.next();
        System.out.println(" size of list 2 iteration x " + size);
        for (int i = 0; i < size; i++) {
          id = (EventID) iterator.next();
          map.put(new ThreadIdentifier(id.getMembershipID(), id.getThreadID()), id.getSequenceID());
        }
      }
    }

    assertThat(
        " Expected the map size to be " + numberOfIterations * 2 * 5 + " but it is " + map.size(),
        map.size(), is(numberOfIterations * 2 * 5));
  }
This test tests remove operation is causing the insertion of a sequence ID for a new
ThreadIdentifier Object ( that is the HA Regio name exists but ThreadIdentifier object is
appearing 1st time) and concurrently the QRM thread is iterating over the Map to form the Data
Set for dispatch. There should not be any DataLoss

In this test, first we add x number of events for unique thread id for the multiples regions
then we start two concurrent threads. One which does add to dispatched events map with sequence
id's greater than x and new ThreadIdentifiers

the second thread does createMessageList (which removes from the dispatched events map) and
stores the list

After the two threads have operated, createMessageList is called again and the data is stored
in another list.

The data in the list is populated on a map against the threadId.

It is then verified to see that the map size should be 2x * number of regions
geode-core/src/integrationTest/java/org/apache/geode/internal/cache/ha/HARegionQueueJUnitTest.java