/**
   * Retrieve, but does not remove, the head of this queue, or returns <tt>null</tt> if this queue
   * is empty. Unlike <tt>poll</tt>, if no expired elements are available in the queue, this method
   * returns the element that will expire next, if one exists.
   *
   * @return the head of this queue, or <tt>null</tt> if this queue is empty.
   */
  @Override
  public QueueElement<E> peek() {
    lock.lock();
    try {
      antiStarvation();
      QueueElement<E> e = null;

      QueueElement<E>[] seeks = new QueueElement[priorities];
      boolean foundElement = false;
      for (int i = priorities - 1; i > -1; i--) {
        e = queues[i].peek();
        debug("peek(): considering [{0}] from P[{1}]", e, i);
        seeks[priorities - i - 1] = e;
        foundElement |= e != null;
      }
      if (foundElement) {
        e = null;
        for (int i = 0; e == null && i < priorities; i++) {
          if (seeks[i] != null && seeks[i].getDelay(TimeUnit.MILLISECONDS) > 0) {
            debug("peek, ignoring [{0}]", seeks[i]);
          } else {
            e = seeks[i];
          }
        }
        if (e != null) {
          debug("peek(): choosing [{0}]", e);
        }
        if (e == null) {
          int first;
          for (first = 0; e == null && first < priorities; first++) {
            e = seeks[first];
          }
          if (e != null) {
            debug("peek(): initial choosing [{0}]", e);
          }
          for (int i = first; i < priorities; i++) {
            QueueElement<E> ee = seeks[i];
            if (ee != null
                && ee.getDelay(TimeUnit.MILLISECONDS) < e.getDelay(TimeUnit.MILLISECONDS)) {
              debug("peek(): choosing [{0}] over [{1}]", ee, e);
              e = ee;
            }
          }
        }
      }
      if (e != null) {
        debug("peek(): [{0}], from P[{1}]", e.getElement().toString(), e.getPriority());
      } else {
        debug("peek(): NULL");
      }
      return e;
    } finally {
      lock.unlock();
    }
  }
 /**
  * Insert the specified {@link QueueElement} element into the queue.
  *
  * @param queueElement the {@link QueueElement} element to add.
  * @param ignoreSize if the queue is bound to a maximum size and the maximum size is reached, this
  *     parameter (if set to <tt>true</tt>) allows to ignore the maximum size and add the element
  *     to the queue.
  * @return <tt>true</tt> if the element has been inserted, <tt>false</tt> if the element was not
  *     inserted (the queue has reached its maximum size).
  * @throws NullPointerException if the specified element is null
  */
 boolean offer(QueueElement<E> queueElement, boolean ignoreSize) {
   if (queueElement == null) {
     throw new NullPointerException("queueElement is NULL");
   }
   if (queueElement.getPriority() < 0 || queueElement.getPriority() >= priorities) {
     throw new IllegalArgumentException("priority out of range: " + queueElement);
   }
   if (queueElement.inQueue) {
     throw new IllegalStateException("queueElement already in a queue: " + queueElement);
   }
   if (!ignoreSize && currentSize != null && currentSize.get() >= maxSize) {
     return false;
   }
   boolean accepted;
   lock.lock();
   try {
     accepted = queues[queueElement.getPriority()].offer(queueElement);
     debug(
         "offer([{0}]), to P[{1}] delay[{2}ms] accepted[{3}]",
         queueElement.getElement().toString(),
         queueElement.getPriority(),
         queueElement.getDelay(TimeUnit.MILLISECONDS),
         accepted);
     if (accepted) {
       if (currentSize != null) {
         currentSize.incrementAndGet();
       }
       queueElement.inQueue = true;
     }
   } finally {
     lock.unlock();
   }
   return accepted;
 }
 /**
  * Promote elements beyond max wait time from a lower priority sub-queue to a higher priority
  * sub-queue.
  *
  * @param lowerQ lower priority sub-queue.
  * @param higherQ higher priority sub-queue.
  * @param msg sub-queues msg (from-to) for debugging purposes.
  */
 private void antiStarvation(
     DelayQueue<QueueElement<E>> lowerQ, DelayQueue<QueueElement<E>> higherQ, String msg) {
   int moved = 0;
   QueueElement<E> e = lowerQ.poll();
   while (e != null && e.getDelay(TimeUnit.MILLISECONDS) < -maxWait) {
     e.setDelay(0, TimeUnit.MILLISECONDS);
     if (!higherQ.offer(e)) {
       throw new IllegalStateException(
           "Could not move element to higher sub-queue, element rejected");
     }
     e.priority++;
     e = lowerQ.poll();
     moved++;
   }
   if (e != null) {
     if (!lowerQ.offer(e)) {
       throw new IllegalStateException(
           "Could not reinsert element to current sub-queue, element rejected");
     }
   }
   debug("anti-starvation, moved {0} element(s) {1}", moved, msg);
 }