C#线程安全集合类说明(1): BlockingCollection<T>

线程安全的集合所在的命名空间 using System.Collections.Concurrent;

Concurrent意思是并发的,并行的。反义是sequential(顺序的),线程安全的意思就是多线程中的同步

System.Collections.Concurrent 命名空间

System.Collections.Concurrent 命名空间提供多个线程安全集合类。当有多个线程并发访问集合时,应使用这些类代替 System.Collections 和 System.Collections.Generic 命名空间中的对应类型。 但是,不保证通过扩展方法或通过显式接口实现访问集合对象是线程安全的,可能需要由调用方进行同步。

BlockingCollection<T>

为实现 IProducerConsumerCollection<T> 的线程安全集合提供阻塞和限制功能。

ConcurrentBag<T>

表示对象的线程安全的无序集合。

ConcurrentDictionary<TKey,TValue>

表示可由多个线程同时访问的键/值对的线程安全集合。

ConcurrentQueue<T>

表示线程安全的先进先出 (FIFO) 集合。

ConcurrentStack<T>

表示线程安全的后进先出 (LIFO) 集合。

OrderablePartitioner<TSource>

表示将可排序数据源拆分为多个分区的特定方式。

Partitioner

提供针对数组、列表和可枚举项的常见分区策略。

Partitioner<TSource>

表示将数据源拆分为多个分区的特定方式。

接口

接口
IProducerConsumerCollection<T>

定义供制造者/使用者用来操作线程安全集合的方法。 此接口提供一个统一的表示(为生产者/消费者集合),从而更高级别抽象如 BlockingCollection<T> 可以使用集合作为基础的存储机制。

枚举

枚举
EnumerablePartitionerOptions

指定控制分区程序的缓冲行为的选项。

 

参考微软官方文档:

https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.concurrent?view=netframework-4.5

参考源代码(类BlockingCollection<T>)

https://referencesource.microsoft.com/#System/sys/system/collections/concurrent/BlockingCollection.cs,0c84922eea8bf511

一、示例:BlockingCollection<T> ,该类与队列ConcurrentQueue<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)
        {
            Console.WriteLine("测试阻塞集合BlockingCollection的添加【Add】和移除【Take】...");
            Task task = AddTakeBlockingCollectionAsync();
            Task.WaitAll(task);
            Console.WriteLine("下面测试阻塞集合BlockingCollection的尝试移除【TryTake】...");
            TryTakeBlockingCollection();
            Console.ReadLine();
        }

        /// <summary>
        /// 阻塞集合BlockingCollection的Add(添加)和Take(移除):生产者【添加元素】、消费者【移除元素】线程安全同时操作
        /// </summary>
        /// <returns></returns>
        static async Task AddTakeBlockingCollectionAsync()
        {
            using (BlockingCollection<int> blockingCollection = new BlockingCollection<int>())
            {
                //生产者
                Task taskProducer = Task.Run(() => 
                {
                    //添加一个元素
                    blockingCollection.Add(1);
                    blockingCollection.Add(2);
                    blockingCollection.Add(3);
                    //结束添加元素:集合已标记为完成添加。CompleteAdding()方法会导致Take()方法出现移除操作异常
                    blockingCollection.CompleteAdding();
                });
                //消费者
                Task taskConsumer = Task.Factory.StartNew(() => 
                {
                    try
                    {
                        while (true)
                        {
                            //移除一个元素,并返回这个移除的元素
                            int removeItem = blockingCollection.Take();
                            Console.WriteLine(removeItem);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"移除项出现异常:{ex.Message}");
                    }
                });
                await Task.WhenAll(taskProducer, taskConsumer);
            }
        }

        /// <summary>
        /// 尝试移除阻塞集合BlockingCollection中的元素
        /// </summary>
        static void TryTakeBlockingCollection()
        {
            using (BlockingCollection<int> bc = new BlockingCollection<int>())
            {
                for (int i = 0; i < 1000; i++)
                {
                    bc.Add(i);
                }
                Console.WriteLine($"是否完成添加:【{bc.IsAddingCompleted}】");
                bc.CompleteAdding();//标记集合已经完成添加
                Console.WriteLine($"是否完成添加:【{bc.IsAddingCompleted}】");

                int outerSum = 0;
                Action action = new Action(() =>
                {
                    int localItem;
                    int sum = 0;
                    while (bc.TryTake(out localItem))
                    {
                        sum += localItem;
                    }
                    Interlocked.Add(ref outerSum, sum);
                    Console.WriteLine($"求和Sum={sum},当前替换:【{outerSum}】");
                });

                //并行操作:三个委托同时执行
                //相当于 将数组求和 分 三小部分数组 分别求和,最后合并
                Parallel.Invoke(action, action, action);
                Console.WriteLine($"此时outerSum为【{outerSum}】");
                Console.WriteLine($"此时集合已完成添加并且集合为空:【{bc.IsCompleted}】");
            }
        }

    }
}

程序运行如图:

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值