.Net 提供了基于生产-消费模式的集合类,这些集合对多线程访问安全,定义在System.Collections.Concurrent名称空间中。这个名称空间中包括基础接口IProduceConsumerCollection,这个接口定义了线程安全集合的基本操作。这个名称空间中还包括常用的集合:

  • BlockingCollection
  • ConcurrentBag
  • ConcurentDictionary<TKey,TValue>
  • ConcurrentQueue
  • ConcurentStack

在使用生产-消费模式时,我们经常使用两个线程,在一个线程向集合添加数据,在另一个线程从集合中提取数据进行处理。我们可以使用实现IProduceConsumerCollection接口的集合,比如ConcurrentQueue等等。通常将从集合取数据的代码放在一个无尽循环中,如果集合中没有数据就继续循环。很多情况下,我们希望如果集合中没有数据,这个线程阻塞等待,直到有数据时再继续。这时我们可以使用BlockingCollection,这个集合提供了Add(添加数据)和Take(阻塞获取数据)方法。

下面是BlockingCollection的示例。这个集合类的Take方法可以从集合中获取并去掉一个对象,当集合为空时,可以使线程处于阻塞状态。

Console.WriteLine("--------------------------------");
Console.WriteLine("测试一个线程向集合添加数据,另一个线程读取数据,请输入人名,输入exit退出");
BlockingCollection<string> names=new BlockingCollection<string>(); Task.Run(() =>
{
while (true)
{
var name = names.Take();
Console.WriteLine("你好,"+name);
} }); var name = Console.ReadLine();
while (name!="exit")
{
if(!string.IsNullOrEmpty(name)) names.Add(name);
name = Console.ReadLine();
}

BlockingCollection的另一个功能是可以封装其它的IProduceConsumerCollection集合,实现不同的添加和获取顺序,比如,如果在构造函数中传入ConcurrentQueue,添加和获取就与队列相同——“先进先出”,如果传入ConcurrentStack,顺序就与堆栈相同——“先进后出”,下面是示例代码:

using System.Collections.Concurrent;

Console.WriteLine("--------------------------------");
Console.WriteLine("测试BlockingCollection 和 ConcurrentQueue"); var queue = new ConcurrentQueue<string>();
var blockqueue= new BlockingCollection<string>(queue, 100); Console.WriteLine("加入name1");
blockqueue.Add("name1");
Console.WriteLine("加入name2");
blockqueue.Add("name2");
Console.WriteLine("加入name3");
blockqueue.Add("name3"); Console.WriteLine(blockqueue.Take());
Console.WriteLine(blockqueue.Take());
Console.WriteLine(blockqueue.Take()); Console.WriteLine("--------------------------------");
Console.WriteLine("测试BlockingCollection 和 ConcurrentStack"); var cq = new ConcurrentStack<string>();
var bc = new BlockingCollection<string>(cq, 100); Console.WriteLine("加入name1");
bc.Add("name1");
Console.WriteLine("加入name2");
bc.Add("name2");
Console.WriteLine("加入name3");
bc.Add("name3"); Console.WriteLine(bc.Take());
Console.WriteLine(bc.Take());
Console.WriteLine(bc.Take());

ConcurrentBag需要特别说明一下,在“纯生产-消费”场景中(一个线程要么向集合添加项目,要么从集合中获取项目,但不能即添加又获取),ConcurrentBag性能要比其他类型的集合慢,但在“混合生产-消费”场景中(一个线程即可以向集合添加项目,也可以获取项目),ConcurrentBag的性能要比其它类型的集合快。

.Net 线程安全集合的更多相关文章

  1. C#的变迁史 - C# 4.0 之线程安全集合篇

    作为多线程和并行计算不得不考虑的问题就是临界资源的访问问题,解决临界资源的访问通常是加锁或者是使用信号量,这个大家应该很熟悉了. 而集合作为一种重要的临界资源,通用性更广,为了让大家更安全的使用它们, ...

  2. 线程安全集合 ConcurrentDictionary<TKey, TValue> 类

    ConcurrentDictionary<TKey, TValue> 类 [表示可由多个线程同时访问的键/值对的线程安全集合.] 支持 .NET Framework 4.0 及以上. 示例 ...

  3. Net线程安全集合

    在看Supersocket源码的时候发现很多地方都用到了我们不是很常用的线程安全集合,这些都是由net优化后的线程安全集合因此 应该比我们常规lock来效率好一些 比如说: 1 CurrentStac ...

  4. 通过Collections将集合转换为线程安全类集合

    通过Collections将集合转换为线程安全类集合 List集合: List<String> list=new ArrayList<String>();list.add(&q ...

  5. Concurrent下的线程安全集合

    1.ArrayBlockingQueue ArrayBlockingQueue是由数组支持的线程安全的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序.这是一个典型的“有界缓存区”,固定 ...

  6. C# 线程安全集合

    转载 对于并行任务,与其相关紧密的就是对一些共享资源,数据结构的并行访问.经常要做的就是对一些队列进行加锁-解锁,然后执行类似插入,删除等等互斥操作. .NetFramework 4.0 中提供了一些 ...

  7. Java创建多线程和线程安全集合Vector

    public class Test { public static Vector<String> data = new Vector<String>(); public sta ...

  8. 在WPF 4.5中跨线程更新集合

    WPF中一个非常强大的功能是数据绑定,我们可以把一个集合绑定到ListBox中,当集合的数据发生变更时,ListBox界面也会同步变更.本身这是一个非常美好的事情,但是美中不足的是:当把集合绑定到Li ...

  9. 最全java多线程总结3——了解阻塞队列和线程安全集合不

      看了前两篇你肯定已经理解了 java 并发编程的低层构建.然而,在实际编程中,应该经可能的远离低层结构,毕竟太底层的东西用起来是比较容易出错的,特别是并发编程,既难以调试,也难以发现问题,我们还是 ...

随机推荐

  1. 转:android相对布局

    android相对布局 Activity布局初步 - 相对布局 1. 相对布局的基本概念 一个控件的位置它决定于它和其他控件的关系,好处:比较灵活:缺点:掌握比较复杂. 2. 相对布局常用属性介绍 这 ...

  2. [BUUCTF]REVERSE——firmware

    firmware 附件 步骤: 检查文件没有看出什么,ida载入一堆乱码,看了其他师傅的wp才知道要先binwalk对文件进行提取 120200.squashfs这是一个linux的压缩文件 我们需要 ...

  3. [BUUCTF]REVERSE——[2019红帽杯]easyRE

    [2019红帽杯]easyRE 附件 步骤: ida载入,没有main函数,就先检索了程序里的字符串 发现了base64加密的特征字符串,双击you found me跟进,找到了调用它的函数,函数很长 ...

  4. [BUUCTF]PWN——jarvisoj_level1

    jarvisoj_level1 附件 步骤: 例行检查,32位程序,没有开任何保护 本地运行一下程序,看看大概的情况,可以看到输出了一个地址 32位ida载入,习惯性的检索程序里的字符串,没有发现可以 ...

  5. C# VS 调试报错:未能加载文件或程序集“Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed”或它的某一个依赖项

    今天在使用 VS(VisualStudio) 调试一个复杂的 WinForm 程序,总是提示错误: 未能加载文件或程序集"Newtonsoft.Json, Version=4.5.0.0, ...

  6. 缓存系统redis操作、mongdb、memeche

    mongdb :默认数据持久化,存在内存的同时也向硬盘写数据. redis:可配置数据持久化,默认数据在内存中 memeche:only support 内存模式 redis操作 https://ww ...

  7. XSS工具类,清除参数中的特殊字符

    package com.xss; import java.util.regex.Pattern; /** * XssUtil 工具类 */ public class XssUtil { static ...

  8. 自动化中不能犯的4个RPA错误-RPA学习天地

    自动化在客户支持中的使用预计在未来几年会加速. 根据Dimension Research的数据,2022年72%的客户互动将通过机器人流程自动化(RPA)等新兴技术进行.电话互动将从41%下降到12% ...

  9. 分享一下java需要的一些技术

    1.前言 you are 大哥,老衲很佩服你们_.还是一样的,有我联系方式的人,哪些半吊子不知道要学习哪些技术,一天让我整知识点,老衲也有事情做的,哪有那么多时间来一直搞知识点啊,我的博客更新很慢的, ...

  10. 【LeetCode】219. Contains Duplicate II 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 使用set 使用字典 日期 题目地址:https:/ ...