actor 模型原理 (二)

现在开始研究一下akka的actor模型是怎么实现的:


老外写了一个程序说明actor的工作机制,下图就是学生给老师发邮件的具体示意图,那么1-6一共6个步骤

1、学生创建actor system ,就是初始化了ActorSystem


2、学生发邮件,发邮件并不是妈的找个163的邮箱直接发一下,或者说并没有直接给邮件地址,而是采用代理的方式,什么意思呢?

就是为了让俩线程,老师和学生更舒服的使用这套通信机制,把后面的邮箱的具体实现都隐藏起来,对于学生来说要做的就是发邮件,发给谁,发给老师


3、这么学生看到的这个老师,其实不是真实的老师,而只是个代理,它负责把这个邮件投递到dispatcher调度器,相当于快递的中转站,这个中转站的功能就是负责接收邮件

接收消息,和投递消息


4、投递消息阶段,投递消息就是塞到另一个actor的邮箱里,按顺序塞进去,你可以理解成塞到你家小区的格格,或者蜂巢那种小箱子里了


5、老师那个actor所在的线程中,会被actor系统投递一个mailbox对象,有了这个对象,就可以在线程中很方便的取东西了


6、每个actor对象实现了一个从mailbox receive 邮件的方法,那么就可以通过这种机制来处理这个消息了



actor 模型原理 (二)_第1张图片



针对上面这个鸡巴图呢,我们再来详细看一下代码怎么做的


一、对于学生这个actor,那么做了三件事

1)创建actorSystem


val system=ActorSystem("UniversityMessageSystem")

创建了一个actorsystem,就等于在学校建立了一套邮件系统,你可以给他取个名字



2) 使用它创建的这个actorsystem,创建一个actorref 即老师的代理

 
  
 val teacherActorRef:ActorRef=actorSystem.actorOf(Props[TeacherActor])

那么自然,参数中要带有老师这个actor的一些配置信息。
akka的actor之间不直接通信,而是采用代理方式,前面已经说过了,是一种优雅的设计,当然你可以实现自己的actor模型
你就是要actor之间直接通信,行不行,当然可以。


3)发送请求消息给这个代理


teacherActorRef!QuoteRequest

一个叹号,就把消息发给邮件中转站了,我啥也不说了,Scala你好吊


完整的学生actor代码可能是这样的:


  //Initialize the ActorSystem
  val actorSystem=ActorSystem("UniversityMessageSystem")

  //construct the Teacher Actor Ref
  val teacherActorRef=actorSystem.actorOf(Props[TeacherActor])

  //send a message to the Teacher Actor
  teacherActorRef!QuoteRequest

  //Let's wait for a couple of seconds before we shut down the system
  Thread.sleep (2000) 

  //Shut down the ActorSystem.
  actorSystem.shutdown()


注意,最后这个

actorSystem.shutdown()

如果不执行这个操作,jvm是不会退出的,上面只是个例子,请求消息发出去之后,实际上需要老师那边异步处理完再关闭整个actor系统的


但是 到底 发了什么东西


前面一个叹号, 就说发了请求消息给老师,那么到底发了啥,QuoteRequest 到底啥东西?


object TeacherProtocol{

  case class QuoteRequest()
  case class QuoteResponse(quoteString:String)

}
这里要提到一个协议的问题,actor通信,实质是线程间通信,actor模型,要求通信双方或者多方,要提供通信协议,按照协议发送请求或者回复请求


二、老师那边的mailbox是个什么鬼


不光是老师,而是所有的actor,每个actor都有一个mailbox,dispatcher会把属于你的消息投递进你的mailbox ,并且消息存储是个FIFO队列

那么在实际生活中,我的邮箱里放在前面的都是最新的邮件,这里要注意区别哈


看到这里你一定在想mailbox可能是个容器,但是其实不是,mailbox其实是个带容器的线程


那么每个actor 本身就是一个线程,这样说每个线程又有一个线程喽?

换句话说,你有多少actor,就有double的线程数了至少


当接收方这个actor想要读取一个消息的时候,mailbox这个线程的run方法就从它这个类的容器里抽出来一个消息 ,然后回调接收方的receive方法

class TeacherActor extends Actor {

  val quotes = List(
    "Moderation is for cowards",
    "Anything worth doing is worth overdoing",
    "The trouble is you think you have time",
    "You never gonna know if you never even try")

  def receive = {

    case QuoteRequest => {

      import util.Random

      //Get a random Quote from the list and construct a response
      val quoteResponse=QuoteResponse(quotes(Random.nextInt(quotes.size)))

      println (quoteResponse)

    }

  }

}


不过这里receive 方法并没有给学生返回任何消息。



你可能感兴趣的:(actor 模型原理 (二))