.Net 线程安全集合
.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 线程安全集合的更多相关文章
- C#的变迁史 - C# 4.0 之线程安全集合篇
作为多线程和并行计算不得不考虑的问题就是临界资源的访问问题,解决临界资源的访问通常是加锁或者是使用信号量,这个大家应该很熟悉了. 而集合作为一种重要的临界资源,通用性更广,为了让大家更安全的使用它们, ...
- 线程安全集合 ConcurrentDictionary<TKey, TValue> 类
ConcurrentDictionary<TKey, TValue> 类 [表示可由多个线程同时访问的键/值对的线程安全集合.] 支持 .NET Framework 4.0 及以上. 示例 ...
- Net线程安全集合
在看Supersocket源码的时候发现很多地方都用到了我们不是很常用的线程安全集合,这些都是由net优化后的线程安全集合因此 应该比我们常规lock来效率好一些 比如说: 1 CurrentStac ...
- 通过Collections将集合转换为线程安全类集合
通过Collections将集合转换为线程安全类集合 List集合: List<String> list=new ArrayList<String>();list.add(&q ...
- Concurrent下的线程安全集合
1.ArrayBlockingQueue ArrayBlockingQueue是由数组支持的线程安全的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序.这是一个典型的“有界缓存区”,固定 ...
- C# 线程安全集合
转载 对于并行任务,与其相关紧密的就是对一些共享资源,数据结构的并行访问.经常要做的就是对一些队列进行加锁-解锁,然后执行类似插入,删除等等互斥操作. .NetFramework 4.0 中提供了一些 ...
- Java创建多线程和线程安全集合Vector
public class Test { public static Vector<String> data = new Vector<String>(); public sta ...
- 在WPF 4.5中跨线程更新集合
WPF中一个非常强大的功能是数据绑定,我们可以把一个集合绑定到ListBox中,当集合的数据发生变更时,ListBox界面也会同步变更.本身这是一个非常美好的事情,但是美中不足的是:当把集合绑定到Li ...
- 最全java多线程总结3——了解阻塞队列和线程安全集合不
看了前两篇你肯定已经理解了 java 并发编程的低层构建.然而,在实际编程中,应该经可能的远离低层结构,毕竟太底层的东西用起来是比较容易出错的,特别是并发编程,既难以调试,也难以发现问题,我们还是 ...
随机推荐
- CSS伪类选择器实现三角形
使用css实现常用的三角效果 项目中三角: .breadcrumb{ height: 40px; line-height: 40px; padding: 0 20px; border-top: 1px ...
- Nginx日志分析脚本
目录 一.简介 二.脚本 一.简介 运维工作是一个比较复杂的工作,有时候面对上万条的日志,如何作分析?难道一条条的分析? 这估计看两眼就要打哈欠了吧?聪明的人会选择脚本,这就是为什么现在提倡自动化运维 ...
- [BUUCTF]PWN15——[BJDCTF 2nd]one_gadget
[BUUCTF]PWN15--[BJDCTF 2nd]one_gadget 附件 步骤: 例行检查,64位,保护全开 nc试运行一下程序,看看情况,它一开始给了我们一个地址,然后让我们输入one ga ...
- 例外日期(Project)
<Project2016 企业项目管理实践>张会斌 董方好 编著 日历无论怎么样自定义,只要仍是存在固化规律的,就铁定会坏事,因为人类的历史就是在大规律中掺杂着无数无规律,再由无数无规律凝 ...
- Eclipse切换不同版本的jdk
var会在java1.8中报错,安装10版本以上的jdk可以解决问题,但是安装后Eclipse无法正常工作,后来发现是Eclipse没有切换版本,在网上找了好多教程都是切换系统变量,后来我发现可以直接 ...
- CF469A I Wanna Be the Guy 题解
Content 小 A 和小 B 正在玩一个游戏,游戏一共有 \(n\) 关,而两个人各只能通过 \(p_A,p_B\) 个关卡.问他们能否通过合作通关这个游戏. 数据范围:\(1\leqslant ...
- java 多线程:线程死锁,如何判断程序是否有死锁代码块儿
线程死锁 死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去(百度百科). 代码示例: /** * @ClassName ...
- tcping和tcpping工具使用
tcping和tcpping工具 1.工具使用 1.1.windows版tcping 1.2.linux版tcpping 2.B站问题(linux版本tcpping探测ip,且ip无法解析到主机名) ...
- Intellij IDEA中Springboot启动报Command line is too long错误
启动报错:Error running 'CmsFrontApplication': Command line is too long. Shorten command line for CmsFron ...
- 【LeetCode】1160. Find Words That Can Be Formed by Characters 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典统计 日期 题目地址:https://leetco ...