private void doFillPatternAdvancedTest(final ChunkSizer chunkSizer) throws InterruptedException {
    // Used to manage worker thread completion
    final CountDownLatch latch = new CountDownLatch(WORKER_THREAD_COUNT);

    // Use to track any errors the worker threads will encounter
    final List<Throwable> threadErrorList =
        Collections.synchronizedList(new LinkedList<>());

    /*
     * Start up a number of worker threads. These threads will randomly allocate, free, and write to
     * Chunks.
     */
    for (int i = 0; i < WORKER_THREAD_COUNT; ++i) {
      new Thread(new Runnable() {
        // Total allocation in bytes for this thread
        private int totalAllocation = 0;

        // List of Chunks allocated by this thread
        private final List<OffHeapStoredObject> chunks = new LinkedList<>();

        // Time to end thread execution
        private final long endTime = System.currentTimeMillis() + RUN_TIME_IN_MILLIS;

        /**
         * Allocates a chunk and adds it to the thread's Chunk list.
         */
        private void allocate() {
          int allocation = chunkSizer.allocationSize();
          OffHeapStoredObject chunk = (OffHeapStoredObject) allocator.allocate(allocation);

          // This should always work just after allocation
          chunk.validateFill();

          chunks.add(chunk);
          totalAllocation += chunk.getSize();
        }

        /**
         * Frees a random chunk from the Chunk list.
         */
        private void free() {
          OffHeapStoredObject chunk = chunks.remove(random.nextInt(chunks.size()));
          totalAllocation -= chunk.getSize();

          /*
           * Chunk is filled here but another thread may have already grabbed it so we cannot
           * validate the fill.
           */
          chunk.release();
        }

        /**
         * Writes canned data to a random Chunk from the Chunk list.
         */
        private void write() {
          OffHeapStoredObject chunk = chunks.get(random.nextInt(chunks.size()));
          chunk.writeDataBytes(0, WRITE_BYTES);
        }

        /**
         * Randomly selects Chunk operations and executes them for a period of time. Collects any
         * error thrown during execution.
         */
        @Override
        public void run() {
          try {
            for (long currentTime = System.currentTimeMillis(); currentTime < endTime; currentTime =
                System.currentTimeMillis()) {
              Operation op = (totalAllocation == 0 ? Operation.ALLOCATE
                  : (totalAllocation >= MAX_WORKER_ALLOCATION_TOTAL_SIZE ? Operation.FREE
                      : Operation.randomOperation()));
              switch (op) {
                case ALLOCATE:
                  allocate();
                  break;
                case FREE:
                  free();
                  break;
                case WRITE:
                  write();
                  break;
              }
            }
          } catch (Throwable t) {
            threadErrorList.add(t);
          } finally {
            latch.countDown();
          }
        }
      }).start();
    }

    // Make sure each thread ended cleanly
    assertTrue(latch.await(2, TimeUnit.MINUTES));

    // Fail on the first error we find
    if (!threadErrorList.isEmpty()) {
      fail(threadErrorList.get(0).getMessage());
    }
  }
This test hammers a MemoryAllocatorImpl with multiple threads exercising the fill validation of
huge Chunks for one minute. This, of course, exercises many aspects of the MemoryAllocatorImpl
and its helper classes.
geode-core/src/integrationTest/java/org/apache/geode/internal/offheap/MemoryAllocatorFillPatternIntegrationTest.java