title: How can I make a Java PriorityBlockingQueue that preserves FIFO behavior?
body: <p>I'm trying to create a <strong>Priority Blocking Queue</strong> in Java that maintains FIFO order for elements with the same priority.  The Oracle doc provides some help with that, but I'm still very tangled up.  </p>
  
  <p>I should note that the following topics are all very new to me: <strong>Generics</strong>, <strong>Interfaces as Types</strong>, and <strong>static nested classes</strong>.  All of these come into play in the following class definition.  Generics, especially, are confusing, and I'm sure I've totally messed up with them here.</p>
  
  <p>I have included comments to identify the compiler errors I am currently getting.</p>
  
  <p>Several specific questions:</p>
  
  <ol>
  <li><p>Is it okay to have the class represent the queued event object, with the actual queue being a static class member?</p></li>
  <li><p>Was it reasonable to have included Oracle's FIFO event "wrapper" as a static nested class?</p></li>
  <li><p>Am I at least on the right track here, doing it all in one outer class?</p></li>
  </ol>
  
  <p>Here is the class that I've written:</p>
  
  <pre><code>import java.util.concurrent.PriorityBlockingQueue;
  import java.util.concurrent.atomic.AtomicLong;
  
  public class FIFOPBQEvent {
  
  /**
   * First we define a static nested class which, when instantiated,
   * encapsulates the "guts" of the event - a FIFOPBQEvent - along with
   * a sequence number that assures FIFO behavior of events of like priority.
   *  
   * The following is lifted ALMOST verbatim (I added "static" and some 
   * comments) from Oracle documentation on adding FIFO-ness to a Priority
   * Blocking Queue: 
   * http://download.oracle.com/javase/6/docs/api/java/util/concurrent/PriorityBlockingQueue.html
   * As the Oracle doc points out:
   * 
   * "A static nested class interacts with the instance members of its outer 
   * class (and other classes) just like any other top-level class. In 
   * effect, a static nested class is behaviorally a top-level class that 
   * has been nested in another top-level class for packaging convenience."
   *
   */
  static class FIFOEntry&lt;E extends Comparable&lt;? super E&gt;&gt; implements
          Comparable&lt;FIFOEntry&lt;E&gt;&gt; {
      final static AtomicLong seq = new AtomicLong();
      final long seqNum;  // instance
      final E entry;
  
      public FIFOEntry(E entry) {
          seqNum = seq.getAndIncrement();
          this.entry = entry;
      }
  
      public E getEntry() {
          return entry;
      }
      /** Here is implementation of Comparable */
      public int compareTo(FIFOEntry&lt;E&gt; other) {
          int res = entry.compareTo(other.entry);
          if (res == 0 &amp;&amp; other.entry != this.entry)
              res = (seqNum &lt; other.seqNum ? -1 : 1);
          return res;
      }
  }
  
  /**
   * Now we declare a single (static) PBQ of FIFO entries into which 
   * PBQFIFOEvents will be added and removed.
   */
  
  /** FLAGGED AS ERROR BY COMPILER */
  // Bound mismatch: The type FIFOPBQEvent is not a valid substitute for the
  // bounded parameter &lt;E extends Comparable&lt;? super E&gt;&gt; of the type 
  // FIFOPBQEvent.FIFOEntry&lt;E&gt;
  
  private static PriorityBlockingQueue&lt;FIFOEntry&lt;FIFOPBQEvent&gt;&gt; theQueue =
      PriorityBlockingQueue&lt;FIFOEntry&lt;FIFOPBQEvent&gt;&gt;();
  
  /** 
   * And here are the "guts" of our event: the i.d. and state of the GUI widget 
   */
  private ConsoleObject obj = ConsoleObject.UNDEFINED_OBJ; // widget that was affected
  private ObjectState state = ObjectState.UNDEFINED_STATE; // the widget's new state
  
  /** 
   * Constructor specifying the class variables 
   */
  public FIFOPBQEvent(ConsoleObject theObj, ObjectState theState) {
      obj = theObj;
      state = theState;
  }
  
  /**
   * Event queuing ("sending") and dequeuing ("receiving")
   */
  public void sendEvent() {
  
      /** FLAGGED AS ERROR BY COMPILER */
      // The method put(FIFOPBQEvent.FIFOEntry&lt;FIFOPBQEvent&gt;) in the type 
      // PriorityBlockingQueue&lt;FIFOPBQEvent.FIFOEntry&lt;FIFOPBQEvent&gt;&gt; is not 
      // applicable for the arguments (FIFOPBQEvent)
  
      theQueue.put(this);
  }
  
  public static FIFOPBQEvent receiveEvent() {
  
      /** FLAGGED AS ERROR BY COMPILER */
      // Type mismatch: cannot convert from FIFOPBQEvent.FIFOEntry&lt;FIFOPBQEvent&gt; 
      // to FIFOPBQEvent
  
      FIFOPBQEvent event = theQueue.take();
      return event;
  }
  
  /**
   * ConsoleEvent accessors
   */
  public ConsoleObject getObj() {
      return this.obj;
  }
  
  public ObjectState getState() {
      return this.state;
  }
  
  /**
   * And for the first time, enums instead of public static final ints.
   */
  public enum ConsoleObject {
      UNDEFINED_OBJ,
      RESERVED,
  
      /** Console keys */
      RESET,
      DISPLAY_MAR,
      SAVE,
      INSERT,
      RELEASE,
      START,
      SIE,
      SCE,
  
      /** Console toggle switches */
      POWER,
      PARITY_CHECK,
      IO_CHECK,
      OVERFLOW_CHECK,
      SENSE_SWITCH_1,
      SENSE_SWITCH_2,
      SENSE_SWITCH_3,
      SENSE_SWITCH_4
  }
  
  public enum ObjectState {
      UNDEFINED_STATE,
  
      /** Toggle switches */
      OFF,
      ON,
  
      /** Console keys */
      PRESSED,
  }
  }
  </code></pre>