面试中本身说话不利落, 或者本身对知识点认识不全面.在这里进行一下记录. 理论部分都是收集(copy)自网上其余的博客.html
参与者模式(英语:Actor model)是一种并发运算上的模型。react
“参与者”是一种抽象概念,被视为并发运算的基本单元:当一个参与者接收到一则消息,它能够作出一些决策、建立更多的参与者、发送更多的消息、决定要如何回答接下来的消息。Actor模型的理念很是简单:天下万物皆为Actor。面试
在使用Java进行并发编程时须要特别的关注锁和内存原子性等一系列线程问题,而Actor模型内部的状态由它本身维护即它内部数据只能由它本身修改(经过消息传递来进行状态修改). redis
1.状态(state):Actor中的状态指的是Actor对象的变量信息,状态由Actor本身管理,避免了并发环境下的锁和内存原子性等问题编程
2.行为(Behavior):行为指定的是Actor中计算逻辑,经过Actor接收到消息来改变Actor的状态并发
3.邮箱(mailBox):邮箱是Actor和Actor之间的通讯桥梁,邮箱内部经过FIFO消息队列来存储发送方Actor消息,接受方Actor从邮箱队列中获取消息. 异步
尽管许多actors同时运行,可是一个actor只能顺序地处理消息。也就是说其它actors发送了三条消息给一个actor,这个actor只能一次处理一条。因此若是你要并行处理3条消息,你须要把这条消息发给3个actors。分布式
消息异步地传送到actor,因此当actor正在处理消息时,新来的消息应该存储到别的地方。Mailbox就是这些消息存储的地方。高并发
当一个actor接收到消息后,它能作以下三件事中的一件:性能
1. Create more actors; 建立其余actors
2. Send messages to other actors; 向其余actors发送消息
3. Designates what to do with the next message. 指定下一条消息到来的行为
一个actor能维持一个私有状态。「指定下一条消息来到作什么」意味着能够定义下条消息来到时的状态。
设想有一个actor像计算器,它的初始状态是数字0。当这个actor接收到add(1)
消息时,它并不改变它本来的状态,而是指定当它接收到下一个消息时,状态会变为1。
1. 事件模型驱动--Actor之间的通讯是异步的,即便Actor在发送消息后也无需阻塞或者等待就可以处理其余事情
2. 强隔离性--Actor中的方法不能由外部直接调用,全部的一切都经过消息传递进行的,从而避免了Actor之间的数据共享,想要观察到另外一个Actor的状态变化只能经过消息传递进行询问.
3. 位置透明--不管Actor地址是在本地仍是在远程机上对于代码来讲都是同样的
4. 轻量性--Actor是很是轻量的计算元,只需少许内存就能达到高并发
5. 若是不用actor模型, 随着项目体量增大,业务越发复杂,不可避免大量使用“锁”,然而“锁”的实际上是很耗性能的,因此大量使用锁的机制确定会形成效率不高. 即便大量依赖“锁”解决了系统中资源竞争的状况,可是因为没有一个规范的编程模式,最后系统的稳定性确定会出问题,最根本的缘由是没把系统的任务调度抽象出来,因为任务调度和业务逻辑的耦合在一块儿,很难作一个很高层的抽象,保证任务调度有序。
6.做为开发者咱们只须要关心每一个Actor的逻辑就能够了,避免“锁”的“滥用”
当全部逻辑都跑在Actor中时,很难掌控Actor的粒度,稍有不慎就可能形成系统中Actor个数爆炸的状况,Actor当出现必须共享数据或者状态时就很难避免使用“锁”,但彷佛因为上面的“Actor可能会堵塞本身,但Actor不该该堵塞它运行的线程”准则冲突,这个时候也许能够选择使用redis作数据共享.
Actor模型有两种任务调度方式:
1. 基于线程的调度:为每一个Actor分配一个线程,在接收一个消息时,若是当前Actor的邮箱(mail box)为空,则会阻塞当前线程。基于线程的调度实现较为简单,但线程数量受到操做的限制,如今的Actor模型通常不采用这种方式;
2. 基于事件的调度:事件能够理解为上述任务或消息的到来,而此时才会为Actor的任务分配线程并执行。
基于线程的调度为每一个Actor分配一个线程,在接受一个消息(如在Scala Actor中使用receive)时,若是当前Actor的“邮箱(mail box)”为空,则会阻塞当前线程直到得到消息为止。基于线程的调度实现起来较为简单. 可是线程数量一多就会影响到系统资源占用以及调度,而在某些状况下大部分的Actor会处于空闲状态,而大量阻塞线程既是系统的负担,也是资源的浪费。所以现有的Actor Model大都不会采起这种方式。
基于事件的调度中, “事件”在这里能够简单理解为“消息到达”事件,而此时才会为Actor的任务分配线程并执行, 既保证了运算资源的充分占用,也不会让系统在同时进行的太多任务中“疲惫不堪”,这样系统即可以获得很好的伸缩性。在Scala Actor中也能够选择使用“react”而不是“recive”方法来使用基于事件的方式来执行任务。
Erlang 引入了「随它崩溃」的哲学理念,这部分关键代码被监控着,监控者的惟一职责是知道代码崩溃后干什么(如将这个单元代码重置为正常状态),让这种理念成为可能的正是actor模型。
每段代码都运行在process中,process是erlang称呼actor的方式。这个process彻底独立,意味着它的状态不会影响其余process。咱们有个supervisor,实际上它只是另外一个process(全部东西都是actor),当被监控的process挂了,supervisor这个process会被通知并对此进行处理。这就让咱们能建立「自愈」系统了。若是一个actor到达异常状态并崩溃,不管如何,supervisor均可以作出反应并尝试把它变成一致状态,这里有不少策略,最多见的是根据初始状态重启actor。
关于actor模型的有趣方面是它并不在乎消息发送到的actor是本地的或者是另外节点上的。
转念一想,若是actor只是一些代码,包含了一个mailbox和一个内部状态,actor只对消息作出响应,谁会关注它运行在哪一个机器上呢?只要咱们能让消息到达就好了。这容许咱们基于许多计算机上构建系统,而且恢复其中任何一台。
好比如今要在3台物理节点上运行一个WordCount做业,能够将这个做业细分为Split、Count和Merge三种任务(任务的target是物理节点的地址,communication可能包含文本、单词及计数等),根据需求要有Split Actor、Count Actor和Merge Actor。整个做业的处理流程如下:
1. Split Actor接收到消息后能够文本分割成10份,每份发送给一个Count Actor;
2. Count Actor统计好单词的数目后发送消息给Merge Actor;
3. Merge Actor收集完Count Actor发送的10个消息后,合并每一个单词的数目,完成WordCount任务。
从以上例子能够看出,Actor系统跟数据驱动系统好比数据流相近,能够自定义任务的流向及其处理过程。
参考博客(就是copy+整理):
https://blog.csdn.net/gulianchao/article/details/7249117
https://www.cnblogs.com/lixiang-share/p/5829437.html