private Runnable consumeQueue() {
      return () -> {
        getPartitionedRegionStats().incVolunteeringThreads(1);
        boolean releaseSemaphore = true;
        try {
          Queue<Runnable> volunteeringQueue = getVolunteeringQueue();
          Runnable queuedWork;
          while (true) {
            // SystemFailure.checkFailure();
            getAdvisee().getCancelCriterion().checkCancelInProgress(null);
            synchronized (volunteeringQueue) {
              // synchronized volunteeringQueue for coordination between threads adding
              // work to the queue and checking for a consuming thread and the existing
              // consuming thread to determine if it can exit since the queue is empty.
              queuedWork = volunteeringQueue.poll();
              if (queuedWork == null) {
                // the queue is empty... no more work... so return
                // @todo why release the semaphore here are sync'ed?
                // we could just let the finally block do it.
                getVolunteeringSemaphore().release();
                releaseSemaphore = false;
                return;
              }
              // still more work in the queue so let's run it
            }
            try {
              queuedWork.run();
            } catch (CancelException e) {
              return;
            } catch (RuntimeException e) {
              // log and continue consuming queue
              logger.error(e.getMessage(), e);
            }
          }
        } finally {
          getPartitionedRegionStats().incVolunteeringThreads(-1);
          if (releaseSemaphore) {
            // Clean up, just in case
            getVolunteeringSemaphore().release();
          }
        }
      };
    }
Returns the runnable used to consume the volunteering queue. The executing thread(s) will
consume from the queue until it is empty.

@return runnable for consuming the volunteering queue
geode-core/src/main/java/org/apache/geode/internal/cache/BucketAdvisor.java