我正在尝试使用SortedDictionary实现优先级队列机制,我想获得有关当前实现的建议。
我的实施如下:
public class PriorityQueue
{
private Object lockObj;
private SortedDictionary<PQMsgPriority, Queue<PQMessage>> messageDictionary;
public PriorityQueue()
{
lockObj = new object();
messageDictionary = new SortedDictionary<PQMsgPriority, Queue<PQMessage>>();
}
public void Enqueue(PQMessage item)
{
lock (lockObj)
{
if(item != null && item.MsgPriority == PQMsgPriority.None)
{
if (messageDictionary.ContainsKey(item.MsgPriority))
{
Queue<PQMessage> dataList = messageDictionary[item.MsgPriority];
dataList.Enqueue(item);
messageDictionary[item.MsgPriority] = dataList;
}
else
{
Queue<PQMessage> dataList = new Queue<PQMessage>();
dataList.Enqueue(item);
messageDictionary.Add(item.MsgPriority, dataList);
}
}
}
}
public PQMessage Dequeue()
{
lock (lockObj)
{
PQMessage messageData = null;
PQMsgPriority deleteKey = PQMsgPriority.None;
//If no data available, throw an exception
if (messageDictionary.Count == 0)
throw new InvalidOperationException();
foreach (KeyValuePair<PQMsgPriority, Queue<PQMessage>> item in messageDictionary)
{
Queue<PQMessage> dataList = item.Value;
messageData = dataList.Dequeue();
messageDictionary[item.Key] = dataList;
//If there is no more elements remaining in the list, set a flag (deleteKey) for deleting the key
if (dataList.Count == 0)
deleteKey = item.Key;
break;
}
//If the deleteKey flag is set, delete the key from the dictionary
if (deleteKey != PQMsgPriority.None)
messageDictionary.Remove(deleteKey);
return messageData;
}
}
public int Count()
{
lock (lockObj)
{
return messageDictionary.Count;
}
}
public PQMessage Peek()
{
lock (lockObj)
{
PQMessage messageData = null;
//If no data available, throw an exception
if (messageDictionary.Count == 0)
throw new InvalidOperationException();
foreach (KeyValuePair<PQMsgPriority, Queue<PQMessage>> item in messageDictionary)
{
Queue<PQMessage> dataList = item.Value;
messageData = dataList.Peek();
break;
}
return messageData;
}
}
}
public enum PQMsgPriority
{
High = 0,
Medium = 1,
Low = 2,
None = 3
}
public class PQMessage
{
private PQMsgPriority msgPriority;
private Object message;
#region Properties
public PQMsgPriority MsgPriority
{
get { return msgPriority; }
set { msgPriority = value; }
}
public Object Message
{
get { return message; }
set { message = value; }
}
#endregion
public PQMessage(PQMsgPriority msgPriority, Object message)
{
this.msgPriority = msgPriority;
this.message = message;
}
}
如果有任何其他方法来实现优先级队列,请指出我正确的方向。
答案 0 :(得分:2)
(我应该放弃这个,因为我假设你是为了学习而不是防弹实现。如果想要一些正常的东西,那么你最好重用现有的实现。)
只是一些一般性评论。在下面的示例中,第三行是不必要的。
Queue<PQMessage> dataList = messageDictionary[item.MsgPriority];
dataList.Enqueue(item);
messageDictionary[item.MsgPriority] = dataList;
从dataList
返回的messageDictionary
是地图中参考的副本。这意味着,当您Enqueue
数据时,它正在与之前相同的底层队列(不是队列的副本)上工作,因此无需再将其重新放回,您只需删除该行即可。
在你的dequeue实现中,你有一个循环,你每次都在第一个元素上打破(例如你只绕过循环一次)。也许您可以调查使用LINQ来获取First
元素并立即返回? (类似于Peek
实施)。
最后,假设PQMessage
本身具有优先权,也许您可以考虑使用SortedList
进行实施? (见here)
答案 1 :(得分:1)
如果您需要提高concurency性能,则只能锁定一个队列进行写入。 (整个SortedDictionary的读锁仍然在线)。
不要忘记按正确的顺序设置和释放锁