我正在尝试在Java中创建优先级阻塞队列,以维护具有相同优先级的元素的FIFO顺序。 Oracle文档对此提供了一些帮助,但是我仍然很纠结。

我应该注意,以下主题对我而言都是非常新的:泛型作为类型的接口(interface)和静态嵌套类。所有这些都在下面的类定义中起作用。泛型尤其令人困惑,我敢肯定,我在这里完全搞砸了它们。

我已包含一些注释,以标识我当前遇到的编译器错误。

几个特定的​​问题:

  • 是否可以让类表示已排队的事件对象,而实际队列是静态类成员呢?
  • 将Oracle的FIFO事件“包装器”包含为静态嵌套类是否合理?
  • 我至少在正确的轨道上,在一个外部类(class)上全部完成了吗?

  • 这是我编写的类(class):
    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<E extends Comparable<? super E>> implements
            Comparable<FIFOEntry<E>> {
        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<E> other) {
            int res = entry.compareTo(other.entry);
            if (res == 0 && other.entry != this.entry)
                res = (seqNum < 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 <E extends Comparable<? super E>> of the type
    // FIFOPBQEvent.FIFOEntry<E>
    
    private static PriorityBlockingQueue<FIFOEntry<FIFOPBQEvent>> theQueue =
        PriorityBlockingQueue<FIFOEntry<FIFOPBQEvent>>();
    
    /**
     * 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<FIFOPBQEvent>) in the type
        // PriorityBlockingQueue<FIFOPBQEvent.FIFOEntry<FIFOPBQEvent>> 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<FIFOPBQEvent>
        // 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,
    }
    }
    

    最佳答案

    第一个错误是更重要的错误。发生这种情况是因为FIFOPBQEvent类未实现Comparable,必须将其视为FIFOEntry嵌套类的通用类型。这是因为您限制E并说它为extends Comparable<...>。基本上,您的FIFOPBQEvent类必须具有可比性,才能为队列提供优先级(大概基于事件类型)。

    要修复该错误,您需要:

  • 将类的标题更改为:
    public class FIFOPBQEvent implements Comparable<FIFOPBQEvent> {
    
  • compareTo类中添加FIFOPBQEvent方法;就像是:
    public int compareTo (FIFOPBQEvent other) {
        // TODO - compare this and other for priority
        return 0;
    }
    

  • 然后,您需要将条目包装在sendEvent方法中:
    public void sendEvent () {
        theQueue.put(new FIFOEntry<FIFOPBQEvent> (this));
    }
    

    最后一个较小的错误就是您没有展开FIFOEntry对象。要解决此问题,请将receiveEvent更改为:
    public static FIFOPBQEvent receiveEvent () {
        FIFOPBQEvent event = theQueue.take ().getEntry ();
        return event;
    }
    

    10-08 16:31