C#中的并发集合Concurrent类
作者:springsnow 发布时间:2021-10-27 03:44:36
一、概述:
System.Collections.Concurrent 命名空间提供多个线程安全集合类。
当有多个线程并发访问集合时,应使用这些类代替 System.Collections 和 System.Collections.Generic 命名空间中的对应类型。
为了对集合进行线程安全的访问,定义了 IProducerConsumerCollection接口。这个接口中最重 要的方法是TryAdd()和TryTake()。
TryAdd()方法尝试给集合添加一项,但如果集合禁止添加项,这个操作就可能失败。为了给出相关信息,TryAdd()方法返回一个布尔值,以说明操作是成功还是失败。
TryTake()方法也以这种方式工作,以通知调用者操作是成功还是失败,并在操作成功时返回集合中的项。
二、空间中包含的类
ConcurrentXXX :这些集合是线程安全的,如果某个动作不适用于线程的当前状态,它们就返回false。在继续之前,总是霈要确认添加或提取元素是否成功。不能相信集合会完成任务。
1、ConcurrentQueue 队列
这个集合类用一种免锁定的算法实现,使用在内部合并到一个链表中的32项数组。
访问队列元素的方法有Enqueue()、TryDequeue()和TryPeek()。这些方法的命名非常类似于前面Queue类的方法,只是给可能调用失败的方法加上了前缀Try。
因为这个类实现了IProducerConsumerCollection接口,所以 TryAdd()和 TryTake()方法仅调用 Enqueue()和 TryDequeue()方法。
2、ConcurrentStack 堆栈
非常类似于ConcurrentQueue类,只是带有另外的元素访问方法。
ConcurrcntStack类定义了 Push()、PushRange()、TryPeek()、TiyPop()和 TryPopRange() 方法。在内部这个类使用其元素的链表。
3、ConcurrentBag 包
该类没有定义添加或提取项的任何顺序。这个类使用一个把线程映射到内部使用的数组上的概念,因此尝试减少锁定。
访问元素的方法有Add()、TryPeek()和 TryTake()。
4、ConcurrentDictionary 字典
——这是一个线程安全的键值集合。
TryAdd()、TryGetValue()、TryRemove()和TryUpdate()方法以非阻塞的方式访问成员。
因为元素基于键和值, 所以 ConcurrentDictionary没有实现 IProducerConsumerCollection。
5、BlockingCollection 集合
这个集合在可以添加或提取元素之前,会阻塞线程并一直等待。
BlockingCollection集合提供了一个接口,以使用Add()和Take()方法来添加和删除元素。 这些方法会阻寒线程,一直等到任务可以执行为止。
Add()方法有一个重载版本,其中可以给该重载版本传递一个CancellationToken令牌。
这个令牌允许取消被阻塞的调用。如果不希望线程无限期地等待下去,且不希望从外部取消调用,就可以使用TryAdd()和 TryTake()方法,在这些方法中,也可以指定一个超时值,它表示在调用失败之前应阻塞线程和等待的最长时间。
6、BlockingCollection 阻塞式集合
这是对实现了 IProducerConsumerCollection接口的任意类的修饰器,它默认使用ConcurrentQueue类。
还可以给构造函数传递任何其他实现了 IProducerConsumerCollection 接口的类。
下面的代码示例简单演示了使用BlockingCollection类和多个线程的过程。
一个线程是生成器,它使用Add()方法给集合写入元素,另一个线程是使用者,它使用Take()方法从集合中提取元素:
internal static BlockingCollection<int> _TestBCollection;
class ThreadWork1 // 生产者
{
public ThreadWork1()
{ }
public void run()
{
System.Console.WriteLine("ThreadWork1 run { ");
for (int i = 0; i < 100; i++)
{
System.Console.WriteLine("ThreadWork1 producer: " + i);
_TestBCollection.Add(i);
}
_TestBCollection.CompleteAdding();
System.Console.WriteLine("ThreadWork1 run } ");
}
}
class ThreadWork2 // 消费者
{
public ThreadWork2()
{ }
public void run()
{
int i = 0;
int nCnt = 0;
bool IsDequeuue = false;
System.Console.WriteLine("ThreadWork2 run { ");
while (!_TestBCollection.IsCompleted)
{
IsDequeuue = _TestBCollection.TryTake(out i);
if (IsDequeuue)
{
System.Console.WriteLine("ThreadWork2 consumer: " + i * i + " =====" + i);
nCnt++;
}
}
System.Console.WriteLine("ThreadWork2 run } ");
}
}
static void StartT1()
{
ThreadWork1 work1 = new ThreadWork1();
work1.run();
}
static void StartT2()
{
ThreadWork2 work2 = new ThreadWork2();
work2.run();
}
static void Main(string[] args)
{
Task t1 = new Task(() => StartT1());
Task t2 = new Task(() => StartT2());
_TestBCollection = new BlockingCollection<int>();//可以跟容量
Console.WriteLine("Sample 4-4 Main {");
Console.WriteLine("Main t1 t2 started {");
t1.Start();
t2.Start();
Console.WriteLine("Main t1 t2 started }");
Console.WriteLine("Main wait t1 t2 end {");
Task.WaitAll(t1, t2);
Console.WriteLine("Main wait t1 t2 end }");
Console.WriteLine("Sample 4-4 Main }");
}
来源:https://www.cnblogs.com/springsnow/p/9511514.html


猜你喜欢
- 命令模式命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳
- LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”,LRU缓存就是使用这种原理实现,简单的说就是缓存一定量
- 1.比较两个字符串时使用“==”还是equals()方法?当然是equals方法。“==”测试的是两个对象的引用是否相同,而equals()
- 前言上一节我们搭建起了服务注册中心,为各个服务提供者和消费者提供一个桥梁,这一节我们搭建一个服务提供者,注册到注册中心开源地址:https:
- 实现方式通过挨个罗列的方式一次复制子对象是非常耗费人力的,如果子对象是引用类型,则还要需要考虑是否对子对象进一步深拷贝。实际应用中,一个类如
- 提到数组大家肯定不会陌生,但我们也知道数组有个缺点就是在创建时就确定了长度,之后就不能更改长度。所以Java官方向我们提供了ArrayLis
- iText介绍和说明因为项目需要生成PDF文件,所以去找了一下能够生成PDF的Java工具,看到了iText可以说好评如潮。如果你想通过ja
- if (textBox1.InvokeRequired) {  
- 本文实例讲述了C#实现读取匿名对象属性值的方法。分享给大家供大家参考,具体如下:通过new出匿名对象,可以直接调用该匿名对象的属性名,获取属
- 多线程细节问题sleep方法和wait方法的异同点?相同点:让线程处于冻结状态.不同点:sleep必须指定时间 wait可以指定时间也可以不
- 本文实例讲述了Android之复选框对话框用法。分享给大家供大家参考。具体如下:main.xml布局文件<?xml version=&
- 刚接触maven就是在公司里配置好的,所以一直以来使用都没毛病,所以一直没有去动这些固有的东西。但是,后来把公司的电脑拿回家之后,发现有的东
- 首先来一道思考题:String str1 = "111111";String str2 = "222222&q
- 问题描述提交表单到servlet时出现空白页面,但又网站不报错截图如下遇到这个问题查找了很多,仍没有解决,刚开始接触IDEA,以为是路径配置
- 这篇文章主要介绍了通过实例了解Java 8创建Stream流的5种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- 1.sonarQube的简介SonarQube是一款自动化代码审查工具,用于检测代码中的错误、漏洞和代码异味。它可以与你现有的工作流集成,以
- 最近总是有人问如何通过Silverlight上传图片并保存的后台服务器?众所周知,Silverlight是客户端程序,不能很好与服务器进行“
- SpringCloud是分布式微服务架构的一站式解决方案,十多种微服务架构落地技术的集合体,俗称微服务全家桶SpringCloud和Spri
- Chart控件可以用来绘制波形图、柱状图、饼图、折线图等,用来进行数据表现是很不错的,现在简单说一下这个控件的使用方法XAML:<Wi
- 本文实例讲述了C#中Params的用法。分享给大家供大家参考。具体方法如下:using System;namespace Params{&n