线程安全的集合所在的命名空间 using System.Collections.Concurrent;
Concurrent意思是并发的,并行的。反义是sequential(顺序的),线程安全的意思就是多线程中的同步锁(相当于增加了lock或Interlocked)
ConcurrentBag<T> 类
表示对象的线程安全的无序集合。相当于 System.Collections.Generic.List<T>在读写的时候增加lock
属性
Count | 获取 ConcurrentBag<T> 中包含的元素数。 |
IsEmpty | 获取一个值,该值指示 ConcurrentBag<T> 是否为空。 |
关键方法:
Add(T) | 将对象添加到 ConcurrentBag<T> 中。 |
ToArray() | 将 ConcurrentBag<T> 元素复制到新数组。 |
TryPeek(T) | 尝试从 ConcurrentBag<T> 返回一个对象但不移除该对象。 |
TryTake(T) | 尝试从 ConcurrentBag<T> 中移除和返回一个对象。 |
当排序并不重要时,包(Bag)可用于存储对象,而与集(HashSet)不同,包支持重复项。 ConcurrentBag<T> 是一个线程安全包实现,适用于同一线程将生成和使用存储在包中的数据的情况。
ConcurrentBag<T> 接受 null
作为引用类型的有效值。
参考微软官方文档:
https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.concurrent?view=netframework-4.5
参考源代码(类BlockingCollection<T>)
测试源程序:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ThreadSafeCollectionDemo
{
class Program
{
static void Main(string[] args)
{
ConcurrentBag<string> bag = new ConcurrentBag<string>();
Console.WriteLine($"当前包的元素个数【{bag.Count}】,是否为空【{bag.IsEmpty}】");
Task task1 = Task.Run(() =>
{
bag.Add("北洛");
bag.Add("云无月");
});
Task task2 = Task.Run(() =>
{
bag.Add("岑缨");
bag.Add("姬轩辕");
});
Task.WaitAll(task1, task2);
//包Bag支持添加重复的元素,和List<T>一样都可以添加重复元素
bag.Add("岑缨");
Console.WriteLine($"当前包的元素个数【{bag.Count}】,是否为空【{bag.IsEmpty}】");
Action action = new Action(() =>
{
string element;
while (bag.TryTake(out element))
{
Console.WriteLine($"取出元素:【{element}】,当前线程编号:【{Thread.CurrentThread.ManagedThreadId}】");
}
});
//分成两部分取出
Parallel.Invoke(action, action);
string result;
if (bag.TryPeek(out result))
{
Console.WriteLine($"包存在元素:【{result}】");
}
else
{
Console.WriteLine("包当前没有元素");
}
Console.WriteLine($"当前包的元素个数【{bag.Count}】,是否为空【{bag.IsEmpty}】");
Console.ReadLine();
}
}
}