线程安全类
ConcurrentQueue
ConcurrentQueue 表示线程安全的先进先出(正序)的集合(线程安全队列)。
常用属性:
名称 | 作用 |
---|---|
Count | 获取安全队列的元素个数 |
IsEmpty | 判断安全队列是否为空,官方建议使用该属性,而不是使用 Count == 0 判断 |
C#
var cq = new ConcurrentQueue<int>();
for (int i = 0; i < 1000; i++)
cq.Enqueue(i);
// 获取队列长度
int count = cq.Count;
// 判断队列是否为空
bool isEmpty = cq.IsEmpty;
常用方法:
名称 | 作用 |
---|---|
Enqueue() | 将元素追加到队列末尾(入队) |
TryDequeue() | 尝试返回队列的第一个元素,并将其从队列移除(出队) |
TryPeek() | 尝试返回队列的第一个元素,但不将其从队列移除 |
Clear() | 清空队列 |
ToArray() | 将队列中的元素复制到一个新数组,可用于遍历 |
Equals() | 判断给定对象与队列是否相等 |
GetType() | 获取队列实例的Type |
C#
// 尝试返回队列的第一个元素,并将其移除
cq.TryDequeue(out int result);
// 尝试返回队列的第一个元素,但不将其移除
cq.TryPeek(out int result);
// 将并发队列中的元素复制到一个新数组
foreach (int item in cq.ToArray())
{
Console.WriteLine(item);
}
// 判断给定对象与队列是否相等
cq.Equals(cq);
// 获取并发队列实例的Type
Type type = cq.GetType();
// 清空队列
cq.Clear();
ConcurrentStack
ConcurrentStack 表示线程安全的后进先出(倒序)集合。
常用属性:
名称 | 作用 |
---|---|
Count | 返回集合的元素个数 |
IsEmpty | 判断集合是否为空 |
C#
var stack = new ConcurrentStack<int>();
Action pusher = () =>
{
for (int i = 0; i < 1000; i++)
stack.Push(i);
};
pusher();
// 获取集合的元素个数
int count = stack.Count;
// 判断集合是否为空
bool isEmpty = stack.IsEmpty;
常用方法:
名称 | 作用 |
---|---|
Push() | 顶部插入一个元素 |
TryPop() | 尝试弹出并返回顶部的对象,会删除该元素 |
TryPeek() | 尝试从顶部获取元素,但不删除该元素 |
PushRange() | 自动将多个对象插入集合顶部 |
ToArray() | 将集合复制到新数组 |
Clear() | 移除集合中的所有元素 |
C#
// 顶部插入一个元素
stack.Push(9999);
// 自动将多个对象插入集合顶部
int[] ints = [1111, 2222, 3333, 4444, 5555];
stack.PushRange(ints);
// 尝试从顶部获取元素,不删除该元素
stack.TryPeek(out int result);
// 尝试获取顶部的对象,删除该元素
stack.TryPop(out int result1);
// 将集合复制到新数组
foreach (int item in stack.ToArray())
{
Console.WriteLine(item);
}
// 移除集合中的所有元素
stack.Clear();
ConcurrentDictionary
ConcurrentDictionary 表示可由多个线程同时访问的 键/值对 的线程安全集合。
常用属性:
名称 | 作用 |
---|---|
Count | 获取线程安全字典的 键值对 个数 |
IsEmpty | 判断线程安全字典是否为空 |
Item[key] | 获取或设置 key 对应的值 |
Keys | 获取线程安全字典所有 键 的集合 |
Values | 获取线程安全字典所有 值 的集合 |
C#
var cd = new ConcurrentDictionary<int, string>();
cd.TryAdd(1, "王一博");
cd.TryAdd(2, "任嘉伦");
int count = cd.Count;
bool isEmpty = cd.IsEmpty;
string? res = cd[1];
ICollection<int>? keys = cd.Keys;
ICollection<string>? values = cd.Values;
常用方法:
名称 | 作用 |
---|---|
TryAdd(key, value) | 尝试添加键值对到字典 |
TryGetValue(key, out var value) | 尝试获取键对应的值 |
TryRemove(key, out var value) | 尝试从字典移除值 |
TryUpdate(key, newVal, comparisonVal) | 尝试更新值,如果 key 对应的值等于 comparisonVal,则替换值为 newVal |
AddOrUpdate() | 添加或更新值,详见示例 |
GetOrAdd() | 获取或添加(如果键不存在,则添加,如果存在,则不添加并返回key对应的值) |
ToArray() | 将原字典复制到新数组中 |
ContainsKey(key) | 判断字典是否包含某个键 |
Clear() | 清空字典 |
C#
// 尝试获取键对应的值
cd.TryGetValue(1, out string? name);
// 尝试从字典移除值
cd.TryRemove(1, out string? name);
cd.TryRemove(1, out string? _);
// 尝试更新值(键 1 对应的值是王一博,则更新为蔡徐坤)
cd.TryUpdate(1, "蔡徐坤", "王一博");
// 添加或更新
cd.AddOrUpdate(1, (key) => "sunny", (key, value) => "sunny");
cd.AddOrUpdate(1, _ => "sunny", (_, _) => "sunny");
cd.AddOrUpdate(1, "sunny", (key, value) => "sunny");
// 获取或添加(如果键 1 不存在,则添加其值为 sunny,如果存在,则返回原始值)
string val = cd.GetOrAdd(1, (key) => "sunny");
// 复制到新数组
foreach (var (key,value) in cd.ToArray())
{
Console.WriteLine($"{key}:{value}");
}
// 判断字典是否包含某个键
bool isContain = cd.ContainsKey(1);
// 清空字典
cd.Clear();
ConcurrentBag
ConcurrentBag<T>
是一个线程安全集合类,适用于存储 无序 对象的集合。
它具有以下优势:
- 线程安全:允许多个线程同时对进行读写操作,无需显式锁定(lock);
- 高吞吐量:专门设计用于多线程环境,具有较高的吞吐量,适合频繁添加和删除元素的场景;
- 无序性:它不关心元素存储的顺序,因此效率更高;
常用属性:
属性 | 作用 |
---|---|
Count | 获取集合元素个数 |
常用方法:
方法 | 作用 |
---|---|
Add() | 向集合添加一个元素 |
TryTake() | 尝试从集合中取出元素,并移除元素 |
TryPeek() | 尝试从集合中取出元素,但不移除元素 |
C#
var bag = new ConcurrentBag<int>();
Parallel.For(0, 100, bag.Add);
var count = bag.Count;
while (bag.TryTake(out int item))
{
Console.WriteLine(item);
}