【问题标题】:How to make a queue switches from FIFO mode to priority mode?如何使队列从 FIFO 模式切换到优先模式?
【发布时间】:2012-09-25 00:32:55
【问题描述】:

我想实现一个能够在 FIFO 模式和优先级模式下运行的队列。这是一个消息队列,优先级首先取决于消息类型:例如,如果A 类型的消息比B 类型的消息具有更高的优先级,那么所有@ 类型的消息987654323@类型的消息先出队列,最后B类型的消息出队列。

优先模式:我的想法是使用多个队列,每种消息一个队列;通过这种方式,我可以根据消息类型管理优先级:只需先从优先级较高的队列中取出消息,然后再从优先级较低的队列中取出。

先进先出模式:如何处理使用多个队列的先进先出模式?换句话说,用户看不到多个队列,但它使用队列就像它是单个队列一样,以便在禁用优先级模式时消息按照它们到达的顺序离开队列。为了实现第二个目标,我曾考虑使用另一个队列来管理消息类型的到达顺序:让我用下面的代码 sn-p 更好地解释一下。

int NUMBER_OF_MESSAGE_TYPES = 4;
int CAPACITY = 50;
Queue[] internalQueues = new Queue[NUMBER_OF_MESSAGE_TYPES];
Queue<int> queueIndexes = new Queue<int>(CAPACITY);

void Enqueue(object message)
{
    int index = ... // the destination queue (ie its index) is chosen according to the type of message.
    internalQueues[index].Enqueue(message);
    queueIndexes.Enqueue(index);
}

object Dequeue()
{
    if (fifo_mode_enabled)
    {
        // What is the next type that has been enqueued?
        int index = queueIndexes.Dequeue();

        return internalQueues[index].Dequeue();
    }

    if (priority_mode_enabled)
    {
        for(int i=0; i < NUMBER_OF_MESSAGE_TYPES; i++)
        {
            int currentQueueIndex = i;
            if (!internalQueues[currentQueueIndex].IsEmpty())
            {
                object result = internalQueues[currentQueueIndex].Dequeue();

                // The following statement is fundamental to a subsequent switching
                // from priority mode to FIFO mode: the messages that have not been
                // dequeued (since they had lower priority) remain in the order in
                // which they were queued.
                queueIndexes.RemoveFirstOccurrence(currentQueueIndex);

                return result;
            }
        }
    }
}

你觉得这个想法怎么样? 有更好或更简单的实现吗?

【问题讨论】:

    标签: oop algorithm language-agnostic


    【解决方案1】:

    应该可以。然而,一目了然,我的想法是

    a) 不是线程安全的,需要做很多工作才能做到这一点。 b)不是异常安全的——即排队或出队的异常可能会留下不一致的状态——也许不是问题,例如如果异常是致命的,但也许是。 c)可能过于复杂和脆弱,尽管我不知道它正在使用的上下文。

    就个人而言,除非我进行了分析并证明存在性能问题,否则我将拥有一个“容器”,并且优先级模式将遍历容器以查找下一个最高优先级的消息 - 毕竟它只有 50 条消息。我几乎肯定会使用链表。我的下一个优化是将一个带有指向每个消息类型的第一个的指针的容器放入该容器中,并在消息出队时更新指针。

    【讨论】:

    • 很好,再简单不过了,50 条消息也可能更快。
    • 我没有写异常处理和线程安全的代码,因为我感兴趣只评估算法:当然,在实现过程中,我会考虑多线程并发访问和异常处理。我指定的 50 条消息的容量只是一个示例,因为实际上我将在一个通用类中实现该算法,您可以在其中设置最大容量:-)
    • 在这种情况下,这种方法是正确的,我个人仍然会在第一次迭代时简化它,但我倾向于在 KISS 方面犯错,我相信修复损坏的“太简单”要容易得多解决方案而不是修复损坏的“过于复杂”的解决方案。我不喜欢实施的一件事是回报——它们有点太隐蔽了。恕我直言,在这种情况下,返回值和单个返回更好。用 else 实现简单,可读性更强。 (我不是“一个出口点”宗教的传教士)
    • ..... 实际上——如果两个值都是假的,再读一遍 Dequeue 就会出现问题——即使它们不能,也应该使用“else”。即“if (fifo_mode_enabled) {...retval = something} else {...retval = something} return retVal”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 2020-03-22
    相关资源
    最近更新 更多