C# .net 集合-并发处理(List集合换成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);
发布了66 篇原创文章 · 获赞 30 · 访问量 28万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览