Dot-Net
如何實現像 .NET 的 ConcurrentBag<T> 這樣的類?
ConcurrentBag<T>我發現自己對即將到來的 .NET 4.0 框架中存在一個類非常感興趣:當訂購無關緊要時,包對於儲存物品很有用,而且與集合不同,包支持重複。
我的問題是:如何實現這個想法?我熟悉的大多數集合基本上相當於(在引擎蓋下)某種形式的數組,其中的順序可能並不“重要”,但有一個順序(這就是為什麼,即使它不需要,列舉也會幾乎總是以相同的順序遍歷未更改的集合,無論是
List、Queue、Stack等)。如果我不得不猜測,我可能會建議在內部它可能是
Dictionary<T, LinkedList<T>>; 但考慮到只使用任何類型T作為鍵是沒有意義的,這實際上似乎很可疑。我期待/希望的是,這實際上是一種已經在某處“弄清楚”的既定對像類型,知道這種既定類型的人可以告訴我。這對我來說太不尋常了——這些概念在現實生活中很容易理解,但作為開發人員很難轉化為可用的類——這就是為什麼我對這些可能性感到好奇的原因。
編輯:
一些響應者建議 a
Bag可能是內部雜湊表的一種形式。這也是我最初的想法,但我預見到這個想法有兩個問題:
- 當您沒有適合所討論類型的雜湊碼函式時,雜湊表並不是那麼有用。
- 簡單地跟踪集合中對象的“計數”與儲存對像不同。
正如 Meta-Knight 所建議的,也許舉個例子可以更清楚地說明這一點:
public class ExpensiveObject() { private ExpensiveObject() { // very intense operations happening in here } public ExpensiveObject CreateExpensiveObject() { return new ExpensiveObject(); } } static void Main() { var expensiveObjects = new ConcurrentBag<ExpensiveObject>(); for (int i = 0; i < 5; i++) { expensiveObjects.Add(ExpensiveObject.CreateExpensiveObject()); } // after this point in the code, I want to believe I have 5 new // expensive objects in my collection while (expensiveObjects.Count > 0) { ExpensiveObject expObj = null; bool objectTaken = expensiveObjects.TryTake(out expObj); if (objectTaken) { // here I THINK I am queueing a particular operation to be // executed on 5 separate threads for 5 separate objects, // but if ConcurrentBag is a hashtable then I've just received // the object 5 times and so I am working on the same object // from 5 threads at the same time! ThreadPool.QueueUserWorkItem(DoWorkOnExpensiveObject, expObj); } else { break; } } } static void DoWorkOnExpensiveObject(object obj) { ExpensiveObject expObj = obj as ExpensiveObject; if (expObj != null) { // some work to be done } }
如果您查看 的詳細資訊
ConcurrentBag<T>,您會發現它在內部基本上是一個自定義的鍊錶。由於 Bags 可以包含重複項,並且不能通過索引訪問,因此雙向鍊錶是一個非常好的實現選擇。這允許鎖定非常細粒度以進行插入和刪除(您不必鎖定整個集合,只需鎖定您插入/刪除的節點)。由於您不擔心重複,因此不涉及散列。這使得雙鍊錶變得完美。