又回到故事時間了,在談談優先性分派前,先來看個真實情境。
在急診室,醫生決定看診的順序,通常是取決於病患的病情急迫程度,而非先到先看。
因此,每位來到急診的患者,在經檢傷醫護人員的評估後,便會被判定一個檢傷分級,級數越嚴重的越優先看診。
這例子與 Priority Queue 的概念相同,但是因為高優先度的資料進入 Queue,就需要重整 Queue 的內容。這樣與 Queue FIFO 的特性有所違背。
我們將不同優先度的資料,視為不同 Queue 的資料。當資料進入時,會自動分配到對應的 Queue 中。而 consumer 向 Dispatch 分派資料,會優先將高優先度的 Queue 的資料分派出去。
class PriorityDispatch<T>
{
private Dictionary<int, ConcurrentQueue<T>> _queues = new Dictionary<int,ConcurrentQueue<T>>();
public void Binding(int priority, ConcurrentQueue<T> queue)
{
_queues[priority] = queue;
}
public T Push()
{
// 取回排序後的優先度
var prioritySet = _queues.Keys.OrderBy(x=>x);
foreach (var priority in prioritySet)
{
if(_queues[priority].IsEmpty)
continue;
_queues[priority].TryDequeue(out var result);
return result;
}
return default(T);
}
}
[TestClass]
public class PriorityDispatchTest
{
[TestMethod]
public void PriorityDispatchTest_當2個queue_只有一個queue有資料()
{
var dispatch = new PriorityDispatch<int>();
var highPriorityQueue = new ConcurrentQueue<int>();
var lowPriorityQueue = new ConcurrentQueue<int>(new[] { 1, 2, 3 });
dispatch.Binding(1, highPriorityQueue);
dispatch.Binding(2, lowPriorityQueue);
List<int> actual = new List<int>();
actual.Add(dispatch.Push());
actual.Add(dispatch.Push());
actual.Add(dispatch.Push());
(new[] { 1, 2, 3 }).ToExpectedObject().ShouldEqual(actual.ToArray());
}
[TestMethod]
public void PriorityDispatchTest_當2個queue_只有均存在資料_輸出為高優先資料在前()
{
var dispatch = new PriorityDispatch<int>();
var highPriorityQueue = new ConcurrentQueue<int>(new[] { 4, 5, 6 });
var lowPriorityQueue = new ConcurrentQueue<int>(new[] { 1, 2, 3 });
dispatch.Binding(1, highPriorityQueue);
dispatch.Binding(2, lowPriorityQueue);
List<int> actual = new List<int>();
actual.Add(dispatch.Push());
actual.Add(dispatch.Push());
actual.Add(dispatch.Push());
actual.Add(dispatch.Push());
actual.Add(dispatch.Push());
actual.Add(dispatch.Push());
(new[] { 4,5,6,1, 2, 3 }).ToExpectedObject().ShouldEqual(actual.ToArray());
}
}