C#基于Redis实现消息队列

环境

Newtonsoft.Json 序列化工具
StackExchange.Redis Redis工具
.net 7.0
项目结构:
在这里插入图片描述

RedisHelper

该帮助类中是包含的Redis的连接和存储的方法

ICache

缓存接口

 public interface ICache
 {
     /// <summary>
     /// 缓存过期时间
     /// </summary>
     int TimeOut { set; get; }
     /// <summary>
     /// 获得指定键的缓存值
     /// </summary>
     /// <param name="key">缓存键</param>
     /// <returns>缓存值</returns>
     object Get(string key);
     /// <summary>
     /// 获得指定键的缓存值
     /// </summary>
     T Get<T>(string key);
     /// <summary>
     /// 从缓存中移除指定键的缓存值
     /// </summary>
     /// <param name="key">缓存键</param>
     void Remove(string key);
     /// <summary>
     /// 清空所有缓存对象
     /// </summary>
     //void Clear();
     /// <summary>
     /// 将指定键的对象添加到缓存中
     /// </summary>
     /// <param name="key">缓存键</param>
     /// <param name="data">缓存值</param>
     void Insert(string key, object data);
     /// <summary>
     /// 将指定键的对象添加到缓存中
     /// </summary>
     /// <param name="key">缓存键</param>
     /// <param name="data">缓存值</param>
     void Insert<T>(string key, T data);
     /// <summary>
     /// 将指定键的对象添加到缓存中,并指定过期时间
     /// </summary>
     /// <param name="key">缓存键</param>
     /// <param name="data">缓存值</param>
     /// <param name="cacheTime">缓存过期时间(秒钟)</param>
     void Insert(string key, object data, int cacheTime);

     /// <summary>
     /// 将指定键的对象添加到缓存中,并指定过期时间
     /// </summary>
     /// <param name="key">缓存键</param>
     /// <param name="data">缓存值</param>
     /// <param name="cacheTime">缓存过期时间(秒钟)</param>
     void Insert<T>(string key, T data, int cacheTime);
     /// <summary>
     /// 将指定键的对象添加到缓存中,并指定过期时间
     /// </summary>
     /// <param name="key">缓存键</param>
     /// <param name="data">缓存值</param>
     /// <param name="cacheTime">缓存过期时间</param>
     void Insert(string key, object data, DateTime cacheTime);
     /// <summary>
     /// 将指定键的对象添加到缓存中,并指定过期时间
     /// </summary>
     /// <param name="key">缓存键</param>
     /// <param name="data">缓存值</param>
     /// <param name="cacheTime">缓存过期时间</param>
     void Insert<T>(string key, T data, DateTime cacheTime);
     /// <summary>
     /// 判断key是否存在
     /// </summary>
     bool Exists(string key);

     /// <summary>
     /// 右侧入队
     /// </summary>
     /// <param name="queueName"></param>
     /// <param name="redisValue"></param>
     /// <returns></returns>
     long EnqueueListRightPush(RedisKey queueName, RedisValue redisValue);
     /// <summary>
     /// 左侧入队
     /// </summary>
     /// <param name="queueName"></param>
     /// <param name="redisvalue"></param>
     /// <returns></returns>
     long EnqueueListLeftPush(RedisKey queueName, RedisValue redisvalue);
     /// <summary>
     /// 获取队列长度
     /// </summary>
     /// <param name="queueName"></param>
     /// <returns></returns>
     long EnqueueListLength(RedisKey queueName);
     /// <summary>
     /// 左侧出队
     /// </summary>
     /// <param name="queueName"></param>
     /// <returns></returns>
     string DequeueListPopLeft(RedisKey queueName);
     /// <summary>
     /// 右侧出队
     /// </summary>
     /// <param name="queueName"></param>
     /// <returns></returns>
     string DequeueListPopRight(RedisKey queueName);
      /// <summary>
       /// Redis发布订阅  订阅
      /// </summary>
       /// <param name="subChannel"></param>
       void RedisSub(string subChannel, Action<string> DealAction);
       /// <summary>
       /// Redis发布订阅  发布
       /// </summary>
      /// <typeparam name="T"></typeparam>
      /// <param name="channel"></param>
      /// <param name="msg"></param>
      /// <returns></returns>
      long RedisPub<T>(string channel, T msg);
      /// <summary>
      /// Redis发布订阅  取消订阅
      /// </summary>
      /// <param name="channel"></param>
      void Unsubscribe(string channel);
      /// <summary>
      /// Redis发布订阅  取消全部订阅
      /// </summary>
      void UnsubscribeAll();
 }

CacheHelper

    /// <summary>
    /// 缓存
    /// </summary>
    public static class CacheHelper
    {
        private static object cacheLocker = new object();//缓存锁对象
        private static ICache cache = null;//缓存接口

        static CacheHelper()
        {
            Load();
        }
        /// <summary>
        /// 指定数据库
        /// </summary>
        /// <param name="database"></param>
       public static void Init(int database=0)
        {
            Load(database);
        }
        /// <summary>
        /// 加载缓存
        /// </summary>
        /// <exception cref=""></exception>
        private static void Load(int Default=0)
        {
            try
            {
                cache = Redis.GetRedis().setDatabase(Default);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static ICache GetCache()
        {
            return cache;
        }


        /// <summary>
        /// 缓存过期时间
        /// </summary>
        public static int TimeOut
        {
            get
            {
                return cache.TimeOut;
            }
            set
            {
                lock (cacheLocker)
                {
                    cache.TimeOut = value;
                }
            }
        }

        /// <summary>
        /// 获得指定键的缓存值
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>缓存值</returns>
        public static object Get(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                return null;
            return cache.Get(key);
        }

        /// <summary>
        /// 获得指定键的缓存值
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>缓存值</returns>
        public static T Get<T>(string key)
        {
            return cache.Get<T>(key);
        }

        /// <summary>
        /// 将指定键的对象添加到缓存中
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        public static void Insert(string key, object data)
        {
            if (string.IsNullOrWhiteSpace(key) || data == null)
                return;
            //lock (cacheLocker)
            {
                cache.Insert(key, data);
            }
        }
        /// <summary>
        /// 将指定键的对象添加到缓存中
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        public static void Insert<T>(string key, T data)
        {
            if (string.IsNullOrWhiteSpace(key) || data == null)
                return;
            //lock (cacheLocker)
            {
                cache.Insert<T>(key, data);
            }
        }
        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间(秒钟)</param>
        public static void Insert(string key, object data, int cacheTime)
        {
            if (!string.IsNullOrWhiteSpace(key) && data != null)
            {
                //lock (cacheLocker)
                {
                    cache.Insert(key, data, cacheTime);
                }
            }
        }

        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间(秒)</param>
        public static void Insert<T>(string key, T data, int cacheTime)
        {
            if (!string.IsNullOrWhiteSpace(key) && data != null)
            {
                //lock (cacheLocker)
                {
                    cache.Insert<T>(key, data, cacheTime);
                }
            }
        }

        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间</param>
        public static void Insert(string key, object data, DateTime cacheTime)
        {
            if (!string.IsNullOrWhiteSpace(key) && data != null)
            {
                //lock (cacheLocker)
                {
                    cache.Insert(key, data, cacheTime);
                }
            }
        }

        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间</param>
        public static void Insert<T>(string key, T data, DateTime cacheTime)
        {
            if (!string.IsNullOrWhiteSpace(key) && data != null)
            {
                //lock (cacheLocker)
                {
                    cache.Insert<T>(key, data, cacheTime);
                }
            }
        }

        /// <summary>
        /// 从缓存中移除指定键的缓存值
        /// </summary>
        /// <param name="key">缓存键</param>
        public static void Remove(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                return;
            lock (cacheLocker)
            {
                cache.Remove(key);
            }
        }

        /// <summary>
        /// 判断key是否存在
        /// </summary>
        public static bool Exists(string key)
        {
            return cache.Exists(key);
        }
        /// <summary>
        /// 右侧入队
        /// </summary>
        /// <param name="queueName"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public static long EnqueueListRightPush(RedisKey queueName, RedisValue redisValue)
        {
            return cache.EnqueueListLeftPush(queueName, redisValue);
        }
        /// <summary>
        /// 左侧入队
        /// </summary>
        /// <param name="queueName"></param>
        /// <param name="redisvalue"></param>
        /// <returns></returns>
        public static bool EnqueueListLeftPush(RedisKey queueName, RedisValue redisvalue)
        {
            if (cache == null)
                return false;
            cache.EnqueueListLeftPush(queueName, redisvalue);
            return true;
        }
        /// <summary>
        /// 获取队列长度
        /// </summary>
        /// <param name="queueName"></param>
        /// <returns></returns>
        public static long EnqueueListLength(RedisKey queueName)
        {
            if(cache == null)
            {
                return 0;
            }
            return cache.EnqueueListLength(queueName);
        }
        /// <summary>
        /// 左侧出队
        /// </summary>
        /// <param name="queueName"></param>
        /// <returns></returns>
        public static string DequeueListPopLeft(RedisKey queueName)
        {
            return cache.DequeueListPopLeft(queueName);
        }
        /// <summary>
        /// 右侧出队
        /// </summary>
        /// <param name="queueName"></param>
        /// <returns></returns>
       public static string DequeueListPopRight(RedisKey queueName)
        {
            return cache.DequeueListPopRight(queueName);
        }
        /// <summary>
        /// Redis发布订阅  订阅
        /// </summary>
        /// <param name="subChannel"></param>
        public static void RedisSub(string subChannel, Action<string> DealAction)
        {
             cache.RedisSub(subChannel, DealAction);
        }
        /// <summary>
        /// Redis发布订阅  发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="channel"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static long RedisPub<T>(string channel, T msg)
        {

            return cache.RedisPub(channel, msg);
        }
        /// <summary>
        /// Redis发布订阅  取消订阅
        /// </summary>
        /// <param name="channel"></param>
        public static void Unsubscribe(string channel)
        {
              cache.Unsubscribe(channel);
        }
        /// <summary>
        /// Redis发布订阅  取消全部订阅
        /// </summary>
        public static void UnsubscribeAll()
        {
            cache.UnsubscribeAll();
        }
    }

redis

这里是reids方法的具体实现,注意这里的redis采用的是单例模式防止产生过多客户端影响系统性能。
在这里插入图片描述

 class CacheObject<T>
 {
     public int ExpireTime { get; set; }
     public bool ForceOutofDate { get; set; }
     public T Value { get; set; }
 }

 public class Redis : ICache
 {
     int Default_Timeout = 3;//默认超时时间(单位秒)
     JsonSerializerSettings jsonConfig = new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Ignore };
     private static readonly string address = "127.0.0.1:6379,password=123456";
     private static Redis uniqueInstance;
     private static readonly object locker = new object();
     ConnectionMultiplexer connectionMultiplexer;
     IDatabase database;
     ISubscriber sub;
    
     public static Redis GetRedis()
     {
         if (uniqueInstance == null)
         {
             lock (locker)
             {
                 // 如果类的实例不存在则创建,否则直接返回
                 if (uniqueInstance == null)
                 {
                     uniqueInstance = new Redis();
                 }
             }
         }
         return uniqueInstance;
     }
    
     private Redis()
     {
         if (address == null || string.IsNullOrWhiteSpace(address.ToString()))
             throw new ApplicationException("配置文件中未找到RedisServer的有效配置");
         connectionMultiplexer = ConnectionMultiplexer.Connect(address);
         connectionMultiplexer.ConnectionFailed += (sender, args) =>
         {
            //redis断开重连
             connectionMultiplexer = ConnectionMultiplexer.Connect(address);
         };
         database = connectionMultiplexer.GetDatabase(0);
         sub = connectionMultiplexer.GetSubscriber();
     }
     /// <summary>
     /// 切换库编号
     /// </summary>
     /// <param name="dbCode"></param>
     /// <returns></returns>
     public Redis setDatabase(int dbCode)
     {
         database = connectionMultiplexer.GetDatabase(dbCode);
         return this;
     }
     /// <summary>
     /// 连接超时设置
     /// </summary>
     public int TimeOut
     {
         get
         {
             return Default_Timeout;
         }
         set
         {
             Default_Timeout = value;
         }
     }

     public object Get(string key)
     {
         return Get<object>(key);
     }

     public T Get<T>(string key)
     {

         DateTime begin = DateTime.Now;
         var cacheValue = database.StringGet(key);
         DateTime endCache = DateTime.Now;
         var value = default(T);
         if (!cacheValue.IsNull)
         {
             var cacheObject = JsonConvert.DeserializeObject<CacheObject<T>>(cacheValue, jsonConfig);
             if (!cacheObject.ForceOutofDate)
                 database.KeyExpire(key, new TimeSpan(0, 0, cacheObject.ExpireTime));
             value = cacheObject.Value;
         }
         DateTime endJson = DateTime.Now;
         return value;

     }
    
     public void Insert(string key, object data)
     {
         var jsonData = GetJsonData(data, TimeOut, false);
         database.StringSet(key, jsonData);
     }

     public void Insert(string key, object data, int cacheTime)
     {
         var timeSpan = TimeSpan.FromSeconds(cacheTime);
         var jsonData = GetJsonData(data, TimeOut, true);
         database.StringSet(key, jsonData, timeSpan);
     }

     public void Insert(string key, object data, DateTime cacheTime)
     {
         var timeSpan = cacheTime - DateTime.Now;
         var jsonData = GetJsonData(data, TimeOut, true);
         database.StringSet(key, jsonData, timeSpan);
     }

     public void Insert<T>(string key, T data)
     {
         var jsonData = GetJsonData<T>(data, TimeOut, false);
         database.StringSet(key, jsonData);
     }

     public void Insert<T>(string key, T data, int cacheTime)
     {
         var timeSpan = TimeSpan.FromSeconds(cacheTime);
         var jsonData = GetJsonData<T>(data, TimeOut, true);
         database.StringSet(key, jsonData, timeSpan);
     }

     public void Insert<T>(string key, T data, DateTime cacheTime)
     {
         var timeSpan = cacheTime - DateTime.Now;
         var jsonData = GetJsonData<T>(data, TimeOut, true);
         database.StringSet(key, jsonData, timeSpan);
     }


     string GetJsonData(object data, int cacheTime, bool forceOutOfDate)
     {
         var cacheObject = new CacheObject<object>() { Value = data, ExpireTime = cacheTime, ForceOutofDate = forceOutOfDate };
         return JsonConvert.SerializeObject(cacheObject, jsonConfig);//序列化对象
     }

     string GetJsonData<T>(T data, int cacheTime, bool forceOutOfDate)
     {
         var cacheObject = new CacheObject<T>() { Value = data, ExpireTime = cacheTime, ForceOutofDate = forceOutOfDate };
         return JsonConvert.SerializeObject(cacheObject, jsonConfig);//序列化对象
     }
     /// <summary>
     /// 删除
     /// </summary>
     /// <param name="key"></param>
     public void Remove(string key)
     {
         database.KeyDelete(key);
     }

     /// <summary>
     /// 判断key是否存在
     /// </summary>
     public bool Exists(string key)
     {
         return database.KeyExists(key);
     }
     /// <summary>
     /// 右侧入队
     /// </summary>
     /// <param name="queueName">队列名称</param>
     /// <param name="redisValue">值</param>
     /// <returns></returns>
     public long EnqueueListRightPush(RedisKey queueName, RedisValue redisValue)
     {
         return database.ListRightPush(queueName, redisValue);
     }
     /// <summary>
     /// 左侧入队
     /// </summary>
     /// <param name="queueName">队列名称</param>
     /// <param name="redisvalue">队列值</param>
     /// <returns></returns>
     public long EnqueueListLeftPush(RedisKey queueName, RedisValue redisvalue)
     {
         return database.ListLeftPush(queueName, redisvalue);
     }
     /// <summary>
     /// 获取队列长度
     /// </summary>
     /// <param name="queueName">队列名称</param>
     /// <returns></returns>
     public long EnqueueListLength(RedisKey queueName)
     {
         if(database.KeyExists(queueName))
         {
             return database.ListLength(queueName);
         }
         else
         {
             return 0;
         }
        
     }
     /// <summary>
     /// 左侧出队
     /// </summary>
     /// <param name="queueName"></param>
     /// <returns></returns>
     public string DequeueListPopLeft(RedisKey queueName)
     {
         var val= database.ListRange(queueName);
         if (val!=null &&val.Length>0 )
         {
             string redisValue = database.ListLeftPop(queueName);
             if (!string.IsNullOrEmpty(redisValue))
                 return redisValue;
             else
                 return string.Empty;
         }
         else
         {
             return "-1";
             throw new Exception($"队列{queueName}数据为零");
         }
     }

     public string DequeueListPopRight(RedisKey queueName)
     {
         var val = database.ListRange(queueName);
         if (val!=null&& val.Length > 0)
         {
             string redisValue = database.ListRightPop(queueName);
             if (!string.IsNullOrEmpty(redisValue))
                 return redisValue;
             else
                 return string.Empty;
         }
         else
         {
             return "-1";
             throw new Exception($"队列{queueName}数据为零");
         }
     }
     /// <summary>
     /// Redis发布订阅  订阅
     /// </summary>
     /// <param name="subChannel"></param>
     public void RedisSub(string subChannel, Action<string> DealAction)
     {
         sub.Subscribe(subChannel, (channel, message) =>
         {
             DealAction((string)message);
             sub.Publish(channel, message);
         });
     }
     /// <summary>
     /// Redis发布订阅  发布
     /// </summary>
     /// <typeparam name="T"></typeparam>
     /// <param name="channel"></param>
     /// <param name="msg"></param>
     /// <returns></returns>
     public long RedisPub<T>(string channel, T msg)
     {

         return sub.Publish(channel, JsonConvert.SerializeObject(msg));
     }
     /// <summary>
     /// Redis发布订阅  取消订阅
     /// </summary>
     /// <param name="channel"></param>
     public void Unsubscribe(string channel)
     {
         sub.Unsubscribe(channel);
     }
     /// <summary>
     /// Redis发布订阅  取消全部订阅
     /// </summary>
     public void UnsubscribeAll()
     {
         sub.UnsubscribeAll();
     }
 }

队列工厂

这里的方法逻辑是,外部方法调用addQueue,往队列里面添加数据,同时开启消费线程(CreateAndRunTask),当数据执行结束后将信号量重置,将线程挂起,减少性能开销
CreateAndRunTask 方法中会调用每个继承该抽象方法的子类的处理方法也就是(DealWith) 方法。

/// <summary>
/// 对列抽象工厂
/// </summary>
public abstract class QueueFactory
{
    /// <summary>
    /// 信号标识
    /// </summary>
    private Lazy<ManualResetEvent> MREvent { get; set; }
    /// <summary>
    /// 消费线程
    /// </summary>
    private Lazy<Task> _Consumption { get; set; }
    /// <summary>
    /// 队列名称
    /// </summary>
    public string QueueName { get; set; }
    public QueueFactory(string _QueueName, int _DbCode = 0)
    {
        CacheHelper.Init(_DbCode);
        QueueName = _QueueName;
        _Consumption = new Lazy<Task>(() => { return CreateAndRunTask(QueueName); });
        MREvent = new Lazy<ManualResetEvent>(() => { return new ManualResetEvent(false); });
    }
    /// <summary>
    /// 队列内添加数据
    /// </summary>
    /// <param name="msg">消息体</param>
    public virtual void addQueue(string message)
    {
        Task.Run(() =>
        {
            try
            {
                if (CacheHelper.EnqueueListLeftPush(QueueName, message))
                {
                    Console.WriteLine(string.Format("[{0}]消息体加入队列:{1}", DateTime.Now.ToString(), message));
                    bool isSet = MREvent.Value.WaitOne(0);//检查当前状态
                    Console.WriteLine(string.Format("[{0}]当前信号量状态:{1}", DateTime.Now.ToString(), isSet.ToString()));
                    if (!isSet)
                    {
                        MREvent.Value.Set();
                        isSet = MREvent.Value.WaitOne(0);
                        Console.WriteLine(string.Format("[{0}]修改后信号量状态:{1}", DateTime.Now.ToString(), isSet.ToString()));
                    }
                    Console.WriteLine(string.Format("[{0}]当前线程状态:{1}", DateTime.Now.ToString(), _Consumption.Value.Status.ToString()));
                    if (_Consumption != null && _Consumption.Value.IsCompleted)
                    {
                        _Consumption.Value.Wait();
                        _Consumption = new Lazy<Task>(() => { return CreateAndRunTask(QueueName); });
                        Console.WriteLine("重新启动线程");
                    }
                }
                else
                {
                    Console.WriteLine(string.Format("[{0}]消息体加入队列时失败消息体内容:{1}", DateTime.Now.ToString(), message));
                };

            }
            catch (Exception ex)
            {
                DealWith(message);
                Console.WriteLine(string.Format("[{0}]Reids未开启!兜底直接处理消息体:{1}", DateTime.Now.ToString(), ex.Message));
            }
        });

    }
    /// <summary>
    /// 消费线程
    /// </summary>
    /// <returns></returns>
    protected virtual Task CreateAndRunTask(string _QueueName)
    {
        return Task.Run(() =>
        {
            long count = CacheHelper.EnqueueListLength(_QueueName);
            if (count > 0)
            {
                for (int i = 0; i <= count; i++)
                {
                    string message = CacheHelper.DequeueListPopRight(_QueueName);
                    if (message == "-1" || string.IsNullOrWhiteSpace(message))
                    {
                        MREvent.Value.Reset();
                    }
                    else
                    {
                        DealWith(message);
                    }
                }
                count = CacheHelper.EnqueueListLength(_QueueName);
                if (count > 0)
                {
                    CreateAndRunTask(_QueueName);
                }
            }
            else
            {
                MREvent.Value.Reset();
            }
        });
    }
    /// <summary>
    /// 消费方法
    /// </summary>
    /// <param name="msg">消息体</param>
    protected abstract void DealWith(string message);
    /// <summary>
    /// 获取队列数量
    /// </summary>
    /// <returns></returns>
    public long GetQueueCount()
    {
        return CacheHelper.EnqueueListLength(QueueName);
    }
}

测试方法

这里是继承自上述基类的子方法
这里重写了Dealwith

 public class TmallQueue : QueueFactory
 {
     public TmallQueue():base("TmallQueue")
     {
             
     }
     protected override void DealWith(string message)
     {
         Console.WriteLine(QueueName + "线程名称:" + Thread.CurrentThread.ManagedThreadId);
         Console.WriteLine(QueueName + "是否为后台线程:" + Thread.CurrentThread.IsBackground);
         Thread.Sleep(1000);
         Console.WriteLine(QueueName+":已处理"+message);
     }
 }

这个方法和上面是同样的

public class MTQueue : QueueFactory
{
    public MTQueue() : base("MTQueue")
    {

    }
    protected override void DealWith(string message)
    {
        Console.WriteLine(QueueName+"线程名称:"+Thread.CurrentThread.ManagedThreadId);
        Console.WriteLine(QueueName + "是否为后台线程:"+Thread.CurrentThread.IsBackground);
        Thread.Sleep(1500);
        Console.WriteLine(QueueName + ":已处理" + message);
    }
}

这里是模拟添加数据


using ConsoleApp1.QueueFactory;

class Program
{
    public static void Main()
    {
        addtest("adss");
        Console.WriteLine("主线程执行结束");
        Console.ReadKey();
    }

  static  string  addtest(string msg)
    {
        MTQueue mT = new MTQueue();

        for (int i = 0; i < 50; i++)
        {
            mT.addQueue(mT.QueueName + "数据" + i+ msg);
            Console.WriteLine(mT.QueueName + "当前队列数量:" + mT.GetQueueCount());
        }
        TmallQueue mTall = new TmallQueue();

        for (int i = 0; i < 50; i++)
        {
            mTall.addQueue(mTall.QueueName + "数据" + i+ msg);
            Console.WriteLine(mTall.QueueName + "当前队列数量:" + mTall.GetQueueCount());
        }
        return msg;
    }
   


}

执行效果:
在这里插入图片描述

源代码下载

点击下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

或与且与或非

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

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

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

打赏作者

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

抵扣说明:

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

余额充值