zoukankan      html  css  js  c++  java
  • 异步简析之BlockingCollection实现生产消费模式

    目前市面上有诸多的产品实现队列功能,比如Redis、MemCache等...
    其实c#中也有一个基础的集合类专门用来实现生产/消费模式 (生产模式还是建议使用Redis等产品)

    下面是官方的一些资料和介绍:

    BlockingCollection 是一个线程安全集合类,可提供以下功能:

    • 实现制造者-使用者模式。

    • 通过多线程并发添加和获取项。

    • 可选最大容量。

    • 集合为空或已满时通过插入和移除操作进行阻塞。

    • 插入和移除“尝试”操作不发生阻塞,或在指定时间段内发生阻塞。

    • 封装实现 IProducerConsumerCollection 的任何集合类型

    • 使用取消标记执行取消操作。

    • 支持使用 foreach(在 Visual Basic 中,使用 For Each)的两种枚举:

      • 只读枚举。

      • 在枚举项时将项移除的枚举。

    BlockingCollection 支持限制和阻塞。 限制意味着可以设置集合的最大容量。 限制在某些情况中很重要,因为它使你能够控制内存中的集合的最大大小,并可阻止制造线程移动到离使用线程前方太远的位置。

    可以看到该类是完全线程安全的,因此用来做生产/消费是非常合适的

    如下代码演示了该类在异步环境中很好的执行着生产和消费任务

    using System;
    using System.Collections.Concurrent;
    using System.Diagnostics;
    using System.Globalization;
    using System.Threading;
    using System.Threading.Tasks;
    using Xunit;
    
    namespace AsyncLearning
    {
        public class TestProduceAndConsumer
        {
            /// <summary>
            /// BlockingCollection是线程安全的集合类型,支持多线程同时读写
            /// </summary>
            private readonly BlockingCollection<string> _blockingQueue =
                new BlockingCollection<string>();
    
    
            private void Produce()
            {
                for (int i = 0; i < 10; i++) //限制生产1000次
                {
                    var now = DateTime.Now.ToString(CultureInfo.InvariantCulture);
                    Debug.WriteLine($"第{i+1}次生产! {now}");
                    _blockingQueue.Add(now);
                    Thread.Sleep(1000);  //特意减慢生产过程以至于不会太快。。。方便演示
                }
    
    
                _blockingQueue.CompleteAdding(); //标记生产完成
            }
    
    
            private void Consume()
            {
                int i = 1;
                while (!_blockingQueue.IsCompleted)
                {
                    var x = _blockingQueue.Take();
                    Debug.WriteLine($"第{i}次消费 {x}");
                    i++;
                    Thread.Sleep(2000);  //故意减慢消费
                }
            }
    
    
            [Fact]
            public void Test()
            {
                
                Task.WaitAll(Task.Run(() => { Produce(); }), Task.Run(() => { Consume(); }));
            }
        }
    }
    

      

    输出如下:

    可见Demo很好的按照设定执行了代码逻辑,由于故意设定了不同的sleep时间,可以看到消费是晚于生产的,而消费全部完成后本Demo的任务全部结束

  • 相关阅读:
    java语言基础1问题汇总
    java从命令行接受多个数字求和输出
    关于Django迁移出现问题
    python中在ubuntu中安装虚拟环境及环境配置
    MVC与MVT
    前端性能优化
    less、sass、stylus
    bootstrap
    Swiper4.x使用方法
    swiper
  • 原文地址:https://www.cnblogs.com/linkanyway/p/produce-consume-task-async.html
Copyright © 2011-2022 走看看