C# .net 集合-并发处理(List<t>集合换成BlockingCollection )

上一节介绍的是并发集合ConcurrentQueue,遇到的问题是当生产者产生数据向队列集合加数据,消费者去消耗这些数据,当队列中数据为空时候,就需要使用sleep来阻塞这个线程,有什么方法可以让集合直接带有阻塞功能呢?这个时候我们就可以使用BlockingCollection。

 static void Main(string[] args)
        {
            int count = 0;
            var queue = new ConcurrentQueue<string>();
            // 生产者线程
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    queue.Enqueue("value" + count);
                    count++;
                }
            });
            // 消费者线程1
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    string value;
                    if (queue.TryDequeue(out value))
                    {
                        Console.WriteLine("Worker 1: " + value);
                    }
                }
            });
            // 消费者线程2
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    string value;
                    if (queue.TryDequeue(out value))
                    {
                        Console.WriteLine("Worker 2: " + value);
                    }

                }
            });


            Thread.Sleep(50000);

            Console.ReadLine();
        }

我们使用BlockingCollection

  static void Main(string[] args)
        {
            int count = 0;
            var blockingCollection = new BlockingCollection<string>();
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    blockingCollection.Add("value" + count);
                    count++;
                }
            });

            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    Console.WriteLine("Worker 1: " + blockingCollection.Take());
                }
            });

            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    Console.WriteLine("Worker 2: " + blockingCollection.Take());
                }
            });

            Thread.Sleep(50000);

            Console.ReadLine();
        }

 BlockingCollection集合是一个拥有阻塞功能的集合,它就 是完成了经典生产者消费者的算法功能。它没有实现底层的存储结构,而是使用了实现IProducerConsumerCollection接口的几个集合 作为底层的数据结构,例如ConcurrentBag, ConcurrentStack或者是ConcurrentQueue。你可以在构造BlockingCollection实例的时候传入这个参数,如果 不指定的话,则默认使用ConcurrentQueue作为存储结构。

  而对于生产者来说,只需要通过调用其Add方法放数据,消费者只需要调用Take方法来取数据就可以了。
  当然了上面的消费者代码中还有一点是让人不爽的,那就是while语句,可以更优雅一点吗?答案还是肯定的:
  

   static void Main(string[] args)
        {
            int count = 0;
            var blockingCollection = new BlockingCollection<string>();

            //生产者
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    blockingCollection.Add("value" + count);
                    count++;
                }
            });


            //消费者
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    Console.WriteLine("Worker 1: " + blockingCollection.Take());
                }
            });
            //消费者写法二
            Task.Factory.StartNew(() =>
            {
                foreach (string value in blockingCollection.GetConsumingEnumerable())
                {
                    Console.WriteLine("Worker 1: " + value);
                }
            });

            Thread.Sleep(50000);

            Console.ReadLine();
        }

 GetConsumingEnumerable()方法是关键,这个方法会遍历集合取出数据,一旦发现集合空了,则阻塞自己,直到集合中又有元素了再开始遍历,神奇吧。

有时候我们要控制一下最大队列数,这个时候我们就可以使用BoundedCapacity来阻止再向队列加数据
BoundedCapacity是用来限制集合的最大容量,当容量已满后,后续的添加操作会被阻塞,一旦有元素被移除,那么阻塞的添加操作会成功执行

//500就是最大容量
     var blockingCollection = new BlockingCollection<string>(500);
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值