MQ(二)Actor模型

什么是 Actor 模型

actor,演员的意思。
Actor 模式是一个解决分布式计算的数学模型,其中 Actor 是基础,它能回应接收到消息,能够自我决策,创建更多的 Actor,发送更多的消息,决定如何回应下一个接收到的消息。
Actor 认为一切皆是 Actor,类似于面向对象认为一切皆 Object 一样。
OO 的执行是顺序的,Actor 模型内在设计就是并行的

Actor 是异步的

Actor 是计算实体,它回复接收到的消息,能够并行的:

  • 发生有限的消息给其他 Actor
  • 创建有限数目的新 Actor
  • 指定一个消息到达时的行为

这些操作并没有顺序要求,它们能够并行地实施。
由于没有对消息的时序做规定,Actor 模式是一种异步模型,发送到 Actor 不等待消息被接收而继续执行。
Actor 之间不共享状态,如果想获取其他 Actor 的状态,只能通过消息请求的方式.

Actor 在消息内部指定接收消息的 Actor 地址。Actor 可以用自己的地址发送消息,相当于自己接收到自己发送的消息,可以驱动自己的状态

所谓真正的 Actor 模型

Actor 可以被认为是在用户空间实现的并发实体,所以它应该是应用级别的线程。
如果认同这个观点那么 Actor 要满足的要求 = 操作系统对进程/线程 提出的要求一样

内存结构

每个并发实体都是要有一个固定的数据结构,必须有一个容器可以保存当前所有的并发实体。
这一点基本上很容易满足,Akka 中 Actor 就是一个类,所以它的结构就是这个类的数据结构,大小也就是这个类的大小。
Akka 中的 Dispatcher 保存有所有 Actor 的列表。

并发原语

操作系统的是通过临界区,锁来定义多线程共享数据模型的。
在 Actor 中是通过消息来共享数据的。
基于消息传递要求“数据只读”,你发送出去的数据再修改肯定就不对了。
但是这一点在 Java 里面无论如何都是做不到的,你不修改变量的引用但是还可以修改变量里面的值,调用对象的方法。
(例如:Java中new一个类,就等于在堆上面新开辟了一个空间,还有一个指针,指向该地址。但是类的实例可以直接或者间接来修改改地址上的值)

调度

这是最重要的:没有调度,并发实体根本不能称之为并发实体。
操作系统中 CPU 是由内核管理的,调度算法是基于时间片来调任务的,内核随时可以剥夺一个任务的 CPU 使用权,这就是“抢占”。
这一点非常重要,没有这个功能就意味着调度是不公平的。
一个任务耗费大量 CPU 会把另个一任务给饿死。
但是在用户空间(应用层)很难实现这一点,毕竟 CPU 是不受应用程序的控制的,没有把办法剥夺。
抢占看似可有可无,但是没有它就没有“公平调度”,也就谈不上并发。(有任务撑死,有任务饿死)

所谓“公平调度”

比如写两个 Actor,使用无限循环输出字符串(while(true))会疯狂的吃 CPU;
如果是可抢占的公平调度,则 actor1 和 actor2 应该是比较有规律的交替(大家得到的 CPU 时间差不多)

Java 中的 Akka

Java中只能开启1000个线程,多了就会出现问题,从根本上原因上就是因为Java的Akka没有实现公平调度。而go语言却能够开启10万个。

test1
test1
test1
...
test2
test2
test2
...
test1
...

ErLang

test1
test2
test1
test2
test1
test2
test1
test2

ErLang 非常均匀的任务切换,实现了“可抢占的公平”

发布了44 篇原创文章 · 获赞 5 · 访问量 918

猜你喜欢

转载自blog.csdn.net/qq_40634246/article/details/104574790