C# 实现 Actor并发模型 (案例版)

啥是Actor模型

Actor (英语翻译 演员) 这个概念要回溯到面向对象程序设计的本身上来,更偏向于现实世界,现实世界就是由单个个体(人)与其他个体或(人)通讯(消息)组成的现实世界,所以,它的好处是显而易见的,生活就是Actor。

现有的面向对象编程模型是基于内存共享线程模型的,而Actor是基于消息模型的,Actor 之间是完全隔离的,不会共享任何变量。

基于内存,那么,内存会溢出,异常,基于消息的话,则没有这种困扰。

又由于它变相的来讲是单线程的,自己处理自己的事务,又实现了与其他业务的隔离。

Erlang语言,天生支持Actor模型,是一个好语言啊。

Actor 的优势

  1. 1. Actor不共享状态

  2. 2. 高并发,无锁(无共享状态)

  3. 3. Actor效率高(同一时刻只处理一个任务,属于单线程处理)

Actor 框架有

  1. 1. Orleans

  2. 2. Dapr

  3. 3. Akka.NET

  4. 4. Proto.Actor

Actor模型的实现

为啥要实现Actor模型,一个是为了更深入的了解它,一个是想实现一下。

可能在某些地方直接就用了。没必要搞那么复杂引用。

Actor模型的原理

按照自己的理解画了一下。

1529d64a695186c7555fb6f48d507e2b.png

简单来讲,就是各个服务都可以投递消息到Actor实例里,Actor会从邮箱里把消息取出来,然后,消费掉。这么简单的一件事情。

Actor 代码逻辑的实现

IActor.cs

/// <summary>
/// 无锁并行编程模型(暂时用来处理串行任务,任务串行执行)
/// </summary>
public interface IActor
{/// <summary>/// 增加消息/// </summary>/// <returns></returns>bool AddMsg(object message);/// <summary>/// 启动服务/// </summary>/// <returns></returns>Task Start();/// <summary>/// 停止服务运行,等待毫秒数/// </summary>/// <param name="WatingTimeout"></param>/// <returns></returns>bool Stop(int WatingTimeout);
}

Actor.cs

/// <summary>
/// Actor抽象
/// </summary>
public abstract class Actor : IDisposable, IActor
{public Actor(string name){Name = name;MailBox = new BlockingCollection<object>();}/// <summary>/// 名称/// </summary>public string Name { get; set; }/// <summary>/// 是否启用/// </summary>public bool Active { get; private set; }/// <summary>/// 是否长时间运行。长时间运行任务使用独立线程,默认true/// </summary>public bool LongRunning { get; set; } = true;/// <summary>/// 处理的消息邮箱/// </summary>public BlockingCollection<object> MailBox { get; set; }/// <summary>/// 内置任务/// </summary>private Task _task;public virtual Task Start(){if (Active) return _task;Active = true;// 启动异步if (_task == null){lock (this){if (_task == null){_task = Task.Factory.StartNew(DoActorWork, LongRunning ? TaskCreationOptions.LongRunning : TaskCreationOptions.None);}}}return _task;}public virtual bool Stop(int WatingTimeout = 100){MailBox?.CompleteAdding();Active = false;if (WatingTimeout == 0 || _task == null) return true;return _task.Wait(WatingTimeout);}public virtual bool AddMsg(object message){// 自动开始if (!Active){Start();}if (!Active){return false;}MailBox.Add(message);return true;}/// <summary>/// 循环消费消息/// </summary>private void DoActorWork(){while (!MailBox.IsCompleted){try{var ctx = MailBox.Take();var task = ProcessAsync(ctx);if (task != null){task.Wait();}}catch (InvalidOperationException) { }catch (Exception ex){Console.WriteLine($"DoActorWork Error : {ex.Message}");}}Active = false;}/// <summary>/// 处理消息/// </summary>/// <returns></returns>public abstract Task ProcessAsync(object msg);public void Dispose(){try{Stop(100);}catch (Exception){}while (MailBox?.TryTake(out _) == true) { }MailBox = null;}
}

相关测试模型

AccumulationActor.cs

/// <summary>
/// 累加
/// </summary>
public class AccumulationActor : Actor
{private int Count = 0;private IActor actor;public AccumulationActor(IActor actor) : base(nameof(AccumulationActor)){Count = 0;this.actor = actor;}   /// <summary>/// 处理信息/// </summary>/// <returns></returns>public override Task ProcessAsync(object msg){try{var  msgNumber = (int)(msg);Count += msgNumber;Console.WriteLine($"处理{this.Name} :{msg} ,累积总数:{Count}");if (Count >= 100){this.actor.AddMsg(Count);Count = 0;}}catch (Exception e){Console.WriteLine($"业务处理异常:{e.Message}");}return Task.CompletedTask;}
}

WriteActor.cs

/// <summary>/// 输出/// </summary>public class WriteActor : Actor{public WriteActor() : base(nameof(WriteActor)){}/// <summary>/// 处理信息/// </summary>/// <returns></returns>public override Task ProcessAsync(object msg){try{Console.WriteLine($"输出 {this.Name} :{msg}");}catch (Exception e){Console.WriteLine($"业务处理异常:{e.Message}");}return Task.CompletedTask;}}

测试代码

static void Main(string[] args)
{Console.Title = "Actor Demo by 蓝创精英团队";//实现一个加法逻辑//a累加到100,就发送消息到 b里,让b 输出。var write = new WriteActor();var User = new AccumulationActor(write);for (int i = 0; i < 20; i++){User.AddMsg(i * 30);}Thread.Sleep(2000);write.Stop();User.Stop();//释放资源Console.WriteLine("示例完毕!");Console.ReadLine();
}

运行结果

7a7288f3f55ed79ed96135a2269ad974.png

总结

上节实现了状态机,这节实现了Actor模型,接下来对Orleans 和 Dapr 的核心原理就了解深入一些了,那么,运用这些技术就不会显的很生涩。

代码地址

https://github.com/kesshei/ActorDemo.git

https://gitee.com/kesshei/ActorDemo.git

一键三连呦!,感谢大佬的支持,您的支持就是我的动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

超详细C语言版数据结构:图的深度优先遍历(推荐收藏)

文章目录一、邻接矩阵存储图的深度优先遍历过程分析二、结果分析三、C语言编程实现图的深度优先遍历四、图的遍历及其应用一、邻接矩阵存储图的深度优先遍历过程分析 对图1这样的无向图&#xff0c;要写成邻接矩阵&#xff0c;则就是下面的式子&#xff1a; 一般要计算这样的问…

Navicat Premium 64 bit 12.1.25

Navicat Premium可让你以单一程序同時连接到 MySQL、MariaDB、SQL Server、SQLite、Oracle 和 PostgreSQL 数据库&#xff0c;是一个可多重连接的数据库管理工具&#xff0c;它让管理不同类型的数据库更加方便。 官方下载地址&#xff1a;https://www.navicat.com.cn/download/…

[JMX一步步来] 7、用JDK5.0的JConsole来连接MBean

前面所有看效果都是通过Html网页来看的。JDK5.0自带了一个jmx客户端&#xff0c;叫jconsole&#xff0c;位于c:\jdk\bin\jconsole.exe。我们来用用这个客户端来连接Mbean Server。一、vm参数方式1、还是用第一篇的那个HelloAgent&#xff0c;修改HelloAgent&#xff0c;将第一句…

记一次 .NET 某新能源系统 线程疯涨 分析

一&#xff1a;背景 1. 讲故事前段时间收到一个朋友的求助&#xff0c;说他的程序线程数疯涨&#xff0c;寻求如何解决。等我分析完之后&#xff0c;我觉得这个问题很有代表性&#xff0c;所以拿出来和大家分享下&#xff0c;还是上老工具 WinDbg。二&#xff1a;WinDbg 分析 1…

[转]ES7、ES8、ES9、ES10新特性大盘点

ES7、ES8、ES9、ES10新特性大盘点 本文转自&#xff1a;https://mp.weixin.qq.com/s/8bov6788ivV0sHzmwrn5lw 以下文章来源于前端工匠 &#xff0c;作者浪里行舟君 前端工匠 我是浪里行舟&#xff0c;Github博客4000star作者&#xff0c;致力于打造一系列能够帮助初中级工程师…

热榜!!!数据结构与算法:C语言版---数组与稀疏矩阵---强势来袭!

数组是各种计算机语言中经常使用到的重要数据结构&#xff0c;一般的说&#xff1a;在内存中申请一片连续地址的存储空间、存储这些数、就称为数组。 在C语言中&#xff0c;申请连续的存储空间是很容易的事情&#xff0c;但难在多维数组的组织、以及数组数据的压缩上&#xff…

第一声问候

前一篇《Emacs 是一台计算机》理解了 Emacs 身为计算机的本质之后&#xff0c;在 Emacs 里编程就顺理成章了。不过&#xff0c;在此之前&#xff0c;还需要略微介绍一下 Emacs 最基本的操作。 系统的不一致&#xff0c;令人有点烦躁 现在&#xff0c;也可以坦然地说&#xff0c…

破解支付宝AR红包

支付宝新出的AR红包没多久&#xff0c;就有人破解了&#xff0c;大致原理是将上面的像素条遮挡下面的黑条&#xff0c;基本上得到模糊的图就可以扫到红包。不过现在大多是ps解决&#xff0c;那得有多麻烦啊&#xff0c;所以我用java写了一个&#xff0c;效果还不错。 先截屏&am…

在 Windows 上搭建配置 Jenkins 然后编译打包 VS 项目

在 Windows 上搭建配置 Jenkins 然后编译打包 VS 项目独立观察员 2022 年 7 月 6 日一、安装1、下载并安装 JRE &#xff08;Java 运行环境&#xff09;。2、下载 Windows 版本的 Jenkins 安装包并安装。3、安装 Visual Studio&#xff0c;以供编译项目使用。4、安装 Advanced …

【ArcGIS微课1000例】0007:基于数字高程模型DEM生成剖面线、剖面图

文章目录 效果预览数据分析工具介绍生成过程剖面图编辑保存、导出剖面图实验数据下载效果预览 数据分析 本实例使用到的原始数据为案例提供的规则格网DEM

[转]javaandroid线程池

java多线程-概念&创建启动&中断&守护线程&优先级&线程状态&#xff08;多线程编程之一&#xff09;java多线程同步以及线程间通信详解&消费者生产者模式&死锁&Thread.join()&#xff08;多线程编程之二&#xff09;java&android线程池-Exe…

.Net下极限生产力之efcore分表分库全自动化迁移CodeFirst

开始本次我们的主题就是极限生产力,其他语言望尘莫及的分表分库全自动化Migrations Code-First 加 efcore 分表分库无感开发还记得上次发布博客还是在上次,上次发布了如何兼容WTM框架后也有不少小伙伴来问我如何兼容如何迁移等问题,经过这么多框架的兼容我自己也认识到了一些问…

Hadoop日常管理与维护

本文描述了hadoop、hbase的启动关闭、表操作以及权限管理。一、Hadoop服务的启动与关闭1、启动使用hadoop以及hbase自带的脚本进行启动&#xff0c;先启动hadoop个服务&#xff0c;再启动hbase服务。 hadoopbdi:~$ start-dfs.sh hadoopbdi:~$ start-yarn.sh hadoopbdi:~$ start…

Mathematica修改默认字体

1. 打开Option Inspector 2. 第一个下拉框选择Global Preference, 搜索stylehints 3. 修改字体为想要换的字体FamilyName, 比如换成苹果黑体 SimHei, 字体FamilyName自行研究 4. 效果 转载于:https://www.cnblogs.com/dabaopku/p/6221960.html

基于JavaScript 数组的经典程序应用源码(强烈建议收藏)

文章目录设计一个数组输入并显示的程序。数组输入和显示选择排序选择排序排序程序包排序网页杨辉三角形杨辉三角形网页C语言画一个sin(x)的曲线螺旋线访问二维数组JavaScript数组的定义、使用都是非常简单的&#xff0c;仅仅定义的话&#xff0c;就使用&#xff1a; var anew …

【ArcGIS微课1000例】0008:ArcGIS中如何设置相对路径?(解决图层前红色的感叹号)

文章目录 问题举例问题分析解决办法问题举例 我们在使用ArcGIS时经常会碰到这样的问题:将地图文档(.mxd)保存到本地并拷贝到别的电脑上或改变一个路径时,出现数据丢失的现象,具体表现为图层前面出现一个红色的感叹号,如下图所示。 出现以上问题的根本原因是数据GSS.tif的…

[转]OKR结合CFR的管理模式

读前预 无论任何管理书籍&#xff0c;都是围绕着人性&#xff0c;如果激发员工的人性中的自尊和自我价值观、自我成就感。 作为一名领导者&#xff0c;在管理前&#xff0c;必须要是冷静&#xff0c;安静的对待他人 约翰杜尔为谷歌送上大礼 “好主意”再加上”卓越的执行”&…

NetCore 国际化最佳实践

NetCore 国际化最佳实践ASP.NET Core中提供了一些本地化服务和中间件&#xff0c;可将网站本地化为不同的语言文化。ASP.NET Core中我们可以使用Microsoft.AspNetCore.Localization库来实现本地化。但是默认只支持使用资源文件方式做多语言存储&#xff0c;很难在实际场景中使用…

复分析——第1章——复分析准备知识(E.M. Stein R. Shakarchi)

第一章 复分析准备知识 (Preliminaries to Complex Analysis) The sweeping development of mathematics during the last two centuries is due in large part to the introduction of complex numbers; paradoxically, this is based on the seemingly absurd no…

【ArcGIS微课1000例】0009:ArcGIS影像拼接(镶嵌、镶嵌至新栅格)

本课程以 DEM数据为例,讲述ArcGIS中影像的拼接方法及注意事项。 文章目录 方法一:Mosaic工具方法二:Mosaic To New Raster工具实验数据下载观察两个数据,接边处切合效果很好。 方法一:Mosaic工具 使用Mosaic工具要千万注意,Mosaic的结果是将输入栅格追加到目标栅格上,…