我發現自己在即將到來的.NET 4.0框架ConcurrentBag<T>
階層的存在很好奇:像.NET的ConcurrentBag <T>這樣的類會如何實現?
袋子是用於存儲訂貨時沒有關係的對象很有用,不像套,包支持重複。
我的問題是:這個想法如何實現?我熟悉的大多數集合實質上(暗中)某種形式的數組,其順序可能並不重要,但是的順序(這就是爲什麼,即使它不需要,枚舉將幾乎總是經歷一個未改變的集合,例如List
,Queue
,Stack
等等)。
如果我不得不猜測,我可能會建議在內部它可能是Dictionary<T, LinkedList<T>>
;但是這實際上似乎很可疑,因爲只使用任何類型T
作爲關鍵是沒有意義的。
我期待/希望的是,這實際上是一個既定的對象類型,已經在某個地方「弄清楚」了,知道這種建立類型的人可以告訴我這個類型。對我來說這很不尋常 - 這些概念在現實生活中很容易理解,但作爲開發人員很難轉化爲可用的類 - 這就是爲什麼我對可能性感到好奇的原因。
編輯:
一些反應表明,一個Bag
可能是一個哈希表的形式在內部。這是我最初的想法是很好,但我預見到兩個問題的想法:
- 散列表是不是所有的有用的,當你沒有有問題的類型合適的哈希碼功能。
- 在集合中跟蹤對象的「數量」與存儲對象並不相同。
爲元騎士建議,也許一個例子將使它更加明確:
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
}
}
+1,因爲它是很好的知道這個類的存在 – Konamiman 2009-11-06 16:54:27
Dan-o:您的示例代碼中的5行註釋是沒有意義的。當然,在這個點你有5個獨立的對象。[public ExpensiveObject CreateExpensiveObject()]中的「new」操作符保證。 – Boogaloo 2009-11-07 00:24:22
嗯..我的錯誤。我以前沒有使用過散列。我假定默認的散列生成器會爲每個對象創建一個唯一的散列值 - 您可以使用自己的散列生成器來覆蓋它。別介意我。 :) – Boogaloo 2009-11-12 00:51:15