根据老赵轻量级Actor进行修改的Actor模型
学习了老赵轻量级Actor模型,并在实际中使用,效果不错。
老赵轻量级Actor模型:
ActorLite:一个轻量级Actor模型实现(上)
ActorLite:一个轻量级Actor模型实现(中)
ActorLite:一个轻量级Actor模型实现(下)
但是在使用此模式的过程中,在message出队列时出现问题,出现queue.count == 0的异常,没能分析出问题的原因,暂时做了一个临时性的解决方案,也并没有测试对性能的影响。
1 /// <summary> 2 /// Actor模型接口 3 /// </summary> 4 internal interface IActor 5 { 6 /// <summary> 7 /// 执行 8 /// </summary> 9 void Execute(); 10 /// <summary> 11 /// 退出标志 12 /// </summary> 13 bool Exited { get; } 14 /// <summary> 15 /// 消息个数 16 /// </summary> 17 int MessageCount { get; } 18 /// <summary> 19 /// Actor上下文 20 /// </summary> 21 ActorContext Context { get; } 22 } 23 24 /// <summary> 25 /// Actor上下文类 26 /// </summary> 27 internal class ActorContext 28 { 29 // 表示某一时期处理消息的状态 30 public int Status; 31 32 /// <summary> 33 /// 保存Actor模型类的引用 34 /// </summary> 35 public IActor Actor { get; private set; } 36 37 /// <summary> 38 /// 构造函数 39 /// </summary> 40 /// <param name="actor"></param> 41 public ActorContext(IActor actor) 42 { 43 this.Actor = actor; 44 } 45 46 // Actor模型执行状态,包括 等待、执行和退出三个状态 47 public const int Waiting = 0; 48 public const int Executing = 1; 49 public const int Exited = 2; 50 } 51 52 /// <summary> 53 /// Actor模型类 54 /// </summary> 55 /// <typeparam name="T"></typeparam> 56 public abstract class Actor<T> : IActor 57 { 58 // Actor上下文对象 59 private readonly ActorContext _context; 60 61 // Exit flag 62 private bool _exited = false; 63 64 // Message queue 65 private readonly ConcurrentQueue<T> _messageQueue = new ConcurrentQueue<T>(); 66 67 /// <summary> 68 /// 投递消息 69 /// </summary> 70 /// <param name="message"></param> 71 public void Post(T message) 72 { 73 if (this._exited) 74 { 75 return; 76 } 77 this._messageQueue.Enqueue(message); 78 // 准备执行处理一个消息 79 Dispatcher.Instance.ReadyToExecute(this); 80 } 81 82 // 接收并处理消息 83 protected abstract void Receive(T message); 84 85 /// <summary> 86 /// Constructor 87 /// </summary> 88 protected Actor() 89 { 90 this._context = new ActorContext(this); 91 } 92 93 #region Properties 94 /// <summary> 95 /// Actor上下文 96 /// </summary> 97 ActorContext IActor.Context 98 { 99 get { return this._context; } 100 } 101 /// <summary> 102 /// 是否退出标志 103 /// </summary> 104 bool IActor.Exited 105 { 106 get { return this._exited; } 107 } 108 /// <summary> 109 /// 消息队列中消息个数 110 /// </summary> 111 int IActor.MessageCount 112 { 113 get { return this._messageQueue.Count; } 114 } 115 #endregion 116 117 /// <summary> 118 /// 处理消息 119 /// </summary> 120 void IActor.Execute() 121 { 122 T message; 123 var dequeueSucess = this._messageQueue.TryDequeue(out message); 124 125 if (dequeueSucess) 126 { 127 this.Receive(message); 128 } 129 } 130 131 protected void Start() 132 { 133 this._exited = false; 134 } 135 /// <summary> 136 /// 退出模式 137 /// </summary> 138 protected void Exit() 139 { 140 this._exited = true; 141 } 142 } 143 144 /// <summary> 145 /// 分发类 146 /// </summary> 147 internal class Dispatcher 148 { 149 // Singleton 150 private static readonly Dispatcher _instance = new Dispatcher(); 151 152 public static Dispatcher Instance 153 { 154 get { return _instance; } 155 } 156 157 /// <summary> 158 /// Private Constructor 159 /// </summary> 160 private Dispatcher() 161 { 162 163 } 164 165 /// <summary> 166 /// 消息预处理:设置处理状态 167 /// </summary> 168 /// <param name="actor"></param> 169 public void ReadyToExecute(IActor actor) 170 { 171 if (actor.Exited) return; 172 // 修改当前状态为执行态 173 int status = Interlocked.CompareExchange(ref actor.Context.Status, ActorContext.Executing, ActorContext.Waiting); 174 175 if (status == ActorContext.Waiting) 176 { 177 // 线程池的可用工作线程处理消息 178 ThreadPool.QueueUserWorkItem(this.Execute, actor); 179 } 180 } 181 182 /// <summary> 183 /// 消息处理 184 /// </summary> 185 /// <param name="o"></param> 186 private void Execute(object o) 187 { 188 IActor actor = (IActor)o; 189 // 190 actor.Execute(); 191 // 如果退出,则设置退出标志位 192 if (actor.Exited) 193 { 194 Thread.VolatileWrite(ref actor.Context.Status, ActorContext.Exited); 195 } 196 // 否则进行下一个消息处理 197 else 198 { 199 Thread.VolatileWrite(ref actor.Context.Status, ActorContext.Waiting); 200 if (actor.MessageCount > 0) 201 { 202 this.ReadyToExecute(actor); 203 } 204 } 205 } 206 }
修改的位置:
1 /// <summary> 2 /// 处理消息 3 /// </summary> 4 void IActor.Execute() 5 { 6 T message; 7 var dequeueSucess = this._messageQueue.TryDequeue(out message); 8 9 if (dequeueSucess) 10 { 11 this.Receive(message); 12 } 13 }
老赵原来的方式:
1 public void Post(T message) 2 { 3 if (this.m_exited) return; 4 5 lock (this.m_messageQueue) 6 { 7 this.m_messageQueue.Enqueue(message); 8 } 9 10 Dispatcher.Instance.ReadyToExecute(this); 11 }
浙公网安备 33010602011771号