集合类的需求总是源源不断,因此,不管是1.0到2.0的泛型,还是3.0到4.0的并行(本文的并行指Concurrent,非 Parallel),.NET每个版本总会伴随着一些集合类的增长。由于并行计算现在已经越来越流行,这里我将对.NET 4.0中新增的命名空间System.Collections.Concurrent和它下面的类做一些简单的介绍。
为什么需要Concurrent?
相信不少朋友都有多线程编程的经历吧,不过在.NET 4.0以前,多线程编程下很容易出问题,先看个简单的例子吧。
static void main()
{
myList = new List<string>();
for (int i = 0; i < 1000; i++)
{
myList.Add(i.ToString());
}
new Thread(T2).Start();
new Thread(T3).Start();
}
static IList<string> myList;
static void T2()
{
Thread.Sleep(100);
for (int i = 0; i < 50; i++)
{
myList.Remove(i.ToString());
}
}
static void T3()
{
foreach (var a in myList)
{
Console.WriteLine(a);
}
}
在这个例子中,我们首先初始化一个长度为1000数组,然后我们开启两个线程,一个进行删除操作,另外个则进行简单的读操作。运行代码的话你会发现程序会抛出InvalidOperationException,因为系统集合在被读的同时被修改了,因此列举操作可能不能执行。
当然在4.0以前我们也有办法避免这种类似的操作,比如我们可以对要操作的对象加锁。即我们可以在对myList集合进行读写操作之前对其添加代码lock (myList)。
然而这种方式毕竟不够简洁,并且在更复杂的情况下它可能会显得非常繁琐。这时候支持并行操作的集合应运而生了。
有哪些Concurrent集合?
在System.Collections.Concurrent公开的类并不多,他们分别在两个不同的dll中存在,其中在System.dll中仅仅一个BlockingCollection<T>和ConcurrentBag<T>,在mscorlib.dll中则稍多一些,他们分别是ConcurrentQueue<T>, ConcurrentStack<T>, ConcurrentDictionary<TKey, TValue>。不过对于日常开发来说,他们基本够用。下面我们来一个个看下这些类的构造吧。
首先看看mscorlib中的几个类,这些类其实我们在.NET 2.0中已经接触过它们的普通版本,因此它们功能基本不变,因此你仍然可以像以前那样使用普通版本的哈希表,队列和堆栈来使用它们。
不过并行类不仅仅简单以前的集合类改造成线程安全的并行类,它同时还提供了一些更丰富的功能,由于Lamda表达式的引入,现在在 ConcurrentDictionary<TKey, TValue>你可以通过AddOrUpdate或GetOrAdd添加自己的值生成方案。这使得我们在生成键值对的时候更加方便和简单了。如:
ConcurrentDictionary<int, string> td = new ConcurrentDictionary<int, string>();
Func<int, string> genVar = (i) => i.ToString();
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 1000; i++)
{
td.GetOrAdd(i, genVar);
}
});
Task.Factory.StartNew(() =>
{
Func<int, string, string> updateVar = (key, oldVar) => oldVar + key;
td.AddOrUpdate(0, genVar, updateVar);
Console.WriteLine(td[0]);
}).Wait();
我们可以看到,现在我们在取值的时候,如果哈希表中没有该值的话我们可以自己生成,或者我们在添加新的值的时候如果碰到重复键值的时候也可以很方便的解决掉了。相对以前在添加或者查找数据时痛苦的判断,这种方式更加简洁和方便。
其他几个类相对来说函数使用变化不大,唯一区别比较大的也是在Concurrent命名空间中很常见的各种try函数操作。
接着我们来看看在System.dll中的并行集合,这里面的两个类在以前的.NET中是没有的。首先看看 ConcurrentBag<T>,顾名思义,这个类提供并行数据包的功能,这个类相对来说构造比较简单,它继承自四个接口:IProducerConsumerCollection<T>, IEnumerable<T>, ICollection, IEnumerable,后面三个集合类常用的接口我们当然很熟悉,而且由于实现了IEnumerable<T>接口,ConcurrentBag<T>也支持LINQ操作。不过这里有个特殊的接口 IProducerConsumerCollection<T>我们以前没有见过,虽然是个新的接口,但故名思意,这个接口提供了生产者/消费者的集合操作,它提供了四个基本的方法:CopyTo(T[],int), ToArray(), TryAdd(T), TryTake(out T)。其中我们主要关注后面的两个方法,TryAdd是添加元素操作,而TryTake则是取元素操作。不过在ConcurrentBag 中,TryAdd方法被设置为protected,外部对象需要通过Add操作来添加元素。另外,取元素的话,除了TryTake之外,我们还可以通过 TryPeek来取集合当前的最后一个元素而不删除它。下面来看看例子:
static void main()
{
ConcurrentBag<string> bag = new ConcurrentBag<string>();
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 1000; i++)
{
bag.Add(i.ToString());
}
bag.Add("Last");
});
Task.Factory.StartNew(() =>
{
foreach (string item in bag)
{
Console.WriteLine(item);
}
}).Wait();
}
BlockingCollection<T>相对来说,要稍微复杂一些,它实现了四个接口:IEnumerable<T>, ICollection, IEnumerable, IDisposable,因此该集合同样支持LINQ,不仅如此,它也提供了比ConcurrentBag更加丰富的功能。如 CompleteAdding和超时设置的TryAdd和TryTake方法等等。
总结
随着多线程和并行编程的要求越来越多,相信在未来,.NET家族新增的这些类将会在我们的日常编程生活中越来越常见,所以掌握它们也显得越来越又必要了。
分享到:
相关推荐
Beginning WF: Windows Workflow in .NET 4.0 (Expert's Voice in .Net) 500 pages Publisher: Apress; 1 edition (March 19, 2010) Language: English ISBN-10: 1430224851 ISBN-13: 978-1430224853 What ...
Chapter 23: System.Transactions . . . . . . . . . . . . . . . . . . . . . . . . . .605 Chapter 24: Networking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 637 Chapter 25: Windows ...
Chapter 23: System.Transactions . . . . . . . . . . . . . . . . . . . . . . . . . .605 Chapter 24: Networking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 637 Chapter 25: Windows ...
主要介绍了Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.Type异常,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
MSDN Library - .NET Framework 4.0 - 命名空间 (节选版) 制作成了chm格式,方便离线状态下学习! ======================================= 原文地址:http://msdn.microsoft.com/zh-cn/library/ms229335.aspx ==...
class : org.apache.jorphan.collections.ListedHashTree required-type : org.apache.jorphan.collections.ListedHashTree converter-type : org.apache.jmeter.save.converters.HashTreeConverter path : /...
.NET Programming with Visual C++: Tutorial, Reference, and Immediate Solutions By 作者: Max Fomitchev ISBN-10 书号: 1138436399 ISBN-13 书号: 9781138436398 Edition 版本: 1 出版日期: 2017-07-27 Pages:...
C#的System.Collections命名空间包含可使用的集合类和相关的接口,提供了集合的基本功能。包括了.NET下的非泛型集合类以及非泛型接口等,现详述如下: 该命名空间下的.NET非泛型集合类如下所示: — System....
列举系统中的环境变量,listView1,System.Collections.DictionaryEntry EnValue in Environment.GetEnvironmentVariables()C#源代码 用VisualStudio2008创建
System.Collections导图,不含泛型(泛型与非泛型基本一致)
泛型接口的实现与非泛型接口的实现的方式相似,免费下载,欢迎支持,正在做 C# 的各集合类型的内部实现,你的支持是我的动力, 谢谢
赠送jar包:commons-collections4-4.1.jar; 赠送原API文档:commons-collections4-4.1-javadoc.jar; 赠送源代码:commons-collections4-4.1-sources.jar; 赠送Maven依赖信息文件:commons-collections4-4.1.pom;...
This new 7th edition of Pro C# 6.0 and the .NET 4.6 Platform has been completely revised and rewritten to reflect the latest changes to the C# language specification and new advances in the .NET ...
Chapter 11• Storing Data in Collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479 Chapter 12• Handling Strings, Characters, and Dates. . . . . . . . . . . . . . . . . . . . 529 ...
该文件里包含两个.jar包: collections-generic-4.01.jar和looks-2.1.4.jar, 引入collections-generic-4.01.jar: 右击工程--》Build path ——》Add External JAR-->选中collections-generic-4.01.jar --》OK 在源...
System.Collections.Generic //命名空间包含定义泛型集合的接口和类,泛型集合允许用户创建强类型集合,它能提供比非泛型强类型集合更好的类型安全性和性能。 System.Configuration //命名空间包含提供用于处理配置...
Hellosam.Net.Collections.BinaryTree 表示以二叉树实现的键/值对(字典)的集合。 Hellosam.Net.Collections.AVLTree 表示在AVL树中实现的键/值对(字典)的集合。 插入,删除,查找操作在O(log n)中 Hellosam...
Kotlin的不可变集合接口和实现原型。
赠送jar包:commons-collections-3.2.2.jar; 赠送原API文档:commons-collections-3.2.2-javadoc.jar; 赠送源代码:commons-collections-3.2.2-sources.jar; 赠送Maven依赖信息文件:commons-collections-3.2.2....