2012-09-25 30 views
0

我想實現一個能夠在FIFO模式和優先模式下運行的隊列。這是一個消息隊列,優先級首先基於消息類型:例如,如果A類型的消息的優先級高於B類型的消息的優先級,則結果所有類型爲A的消息都先出列,最後出現B類型的消息。如何使隊列從FIFO模式切換到優先模式?

優先模式:我的想法包括使用多個隊列,每個隊列用於每種類型的消息;通過這種方式,我可以根據消息類型管理優先級:只需從優先級較高的隊列中首先獲取消息,然後再從較低優先級的隊列中逐步獲取消息。

FIFO模式:如何使用多個隊列處理FIFO模式?換句話說,用戶沒有看到多個隊列,但它使用隊列,就好像它是單個隊列一樣,以便消息在優先級模式被禁用時按照它們到達的順序離開隊列。爲了實現這個第二個目標,我想用另一個隊列來管理消息類型的到達順序:讓我用下面的代碼片段更好地解釋。

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; 
      } 
     } 
    } 
} 

您對這個想法有什麼看法? 有更好還是更簡單的實現?

回答

2

應該工作。然而,在一瞥我的想法是

a)不是線程安全的和大量的工作,使它如此。 b)不是例外的安全 - 即排隊或排隊的例外可能會導致不一致的狀態 - 可能不是問題,例如,如果例外是致命的,但也許是。 c)可能過於複雜和脆弱,但我不知道它正在使用的上下文。我個人有一個「容器」,優先模式會遍歷容器尋找下一個最高優先級的消息 - 畢竟它只有50條消息。除非我已經介紹過並且顯示出性能問題,否則我將擁有一個「容器」。我幾乎肯定會使用鏈表。我的下一個優化是將一個容器指向每個消息類型的第一個指向該容器的指針,並更新消息出隊指針。

+0

不錯,它不能做得更簡單,而且有50條消息可能更快。 – maaartinus

+0

我沒有編寫異常處理和線程安全的代碼,因爲我只關心評估算法:當然,在實現過程中,我會考慮多線程的併發訪問和異常處理。我所指定的50條消息的容量僅僅是一個例子,因爲實際上我將在一個可以設置最大容量的泛型類中實現算法:-) – enzom83

+0

在這種情況下,這種方法是正確的我仍然會在第一次迭代時簡化它,但我傾向於在KISS方面犯錯誤,我相信修復破損的「太簡單」解決方案要比修復破碎的「太複雜」解決方案容易得多。我不喜歡實現的一件事是回報 - 它們有點太埋了。恕我直言,在這種情況下返回值和單一回報更好。簡單實現與其他和更具可讀性。 (我不是「一個退出點」宗教的傳道者) – mattnz