Akka笔记–演员信息– 1

从Akka Notes的介绍性第一部分中,我们在Akka Toolkit中看到了Actor的鸟瞰图。 在Akka Notes的第二部分中,我们将研究Actors的消息传递部分。 对于该示例,我们将使用前面讨论的相同的Student-Teacher示例。

在Actor Messaging的第一部分中,我们将创建Teacher Actor,而不是Student Actor,将使用一个名为StudentSimulatorApp的主程序。

再探学生老师

现在,让我们考虑一下StudentSimulatorApp仅发送给TeacherActor的消息。 当我说StudentSimulatorApp ,我只是说一个普通的主程序。

Akka笔记–演员信息– 1_第1张图片

图片传达了这一点:

(如果您的条款过于笼统,请放心,我们将详细介绍这些条款)

  1. 学生创建一个称为ActorSystem东西
  2. 它使用ActorSystem创建称为ActorRef QuoteRequest消息发送到ActorRef(TeacherActor的代理)
  3. Actor ref将消息传递到Dispatcher
  4. 分派器将消息放入目标Actor的MailBox
  5. 然后,分派器将Mailbox放在线程上(在下一节中有更多介绍)。
  6. MailBox使消息出队,并最终将其委派给实际的教师演员的接收方法。

就像我说的,不用担心。 现在让我们详细了解每个步骤。 完成后,您可以返回并重新访问这五个步骤。

我们将使用此StudentSimulatorApp来启动JVM并初始化ActorSystem。

Akka笔记–演员信息– 1_第2张图片

从图片中我们可以看出,StudentSimulatorApp

  1. 创建一个Actor系统
  2. 使用ActorSystem创建教师演员(ActorRef)的代理
  3. 将QuoteRequest消息发送到代理。

现在让我们仅关注这三点。

  1. 创建一个Actor系统

  2. ActorSystem是ActorWorld的入口点。 您可以通过ActorSystems创建和停止Actor。 甚至关闭整个Actor环境。

    另一方面,Actor是分层的,ActorSystem也类似于java.lang.Objectscala.Any适用于所有Actor,这意味着它是所有Actor的根。 使用ActorSystem的actorOf方法创建Actor时,将在ActorSystem下方创建一个Actor。

    Akka笔记–演员信息– 1_第3张图片

    初始化ActorSystem的代码如下:

    val system=ActorSystem("UniversityMessageSystem")

    UniversityMessageSystem只是您为ActorSystem赋予的可爱名称。

  3. 为TeacherActor创建代理?

  4. 让我们考虑以下代码段:

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

    actorOfactorOf中Actor的创建方法。 但是,正如您所看到的,它没有返回我们需要的TeacherActor。 它返回ActorRef类型的ActorRef

    ActorRef充当实际Actor的代理。 客户不直接与演员交谈。 为此,Actor模型避免了直接访问TeacherActor或任何Actor中的任何自定义/私有方法或变量的方式。

    要重复,您只将消息发送到ActorRef,最终它会到达您的实际Actor。 您永远不能直接与演员交谈。 如果您发现一些卑鄙的方法,人们会恨死您。

    Akka笔记–演员信息– 1_第4张图片

  5. 发送QuoteRequest到代理

  6. 这又是一个班轮。 您只需将QuoteRequest消息tell ActorRef。 Actor中的tell方法实际上是! (ActorRef中还有一个tell方法,它将调用委托给! )。

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

    而已 !!!

如果您认为我在撒谎,请检查以下StudentSimulatorApp的完整代码:

StudentSimulatorApp.scala

package me.rerun.akkanotes.messaging.firenforget

import akka.actor.ActorSystem  
import akka.actor.Props  
import akka.actor.actorRef2Scala  
import me.rerun.akkanotes.messaging.protocols.TeacherProtocol._


object StudentSimulatorApp extends App{

  //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()

}

好吧,我有点作弊。 您必须shutdown ActorSystem,否则JVM会一直运行。 而且我正在使主线程休眠一会儿,只是为了让TeacherActor完成任务。 我知道这听起来很愚蠢。 不用担心 为了避免这种攻击,我们将在下一部分中编写一些简洁的测试用例。

讯息

我们只是一个QuoteRequest 告诉QuoteRequest ,但我们根本没有看到消息类!

它来了 :

(建议将消息​​包装在一个不错的对象中,以方便组织)

教师协议

package me.rerun.akkanotes.messaging.protocols

object TeacherProtocol{

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

}

如您所知, QuoteRequest是针对来到TeacherActor的请求的。 Actor将使用QuoteResponse响应。

调度程序和邮箱

ActorRef将消息处理功能委托给Dispatcher ActorSystem ,当我们创建ActorSystemActorRef ,创建了DispatcherMailBox 让我们看看它们的含义。

Akka笔记–演员信息– 1_第5张图片

邮箱

Ever Actor拥有一个MailBox(我们将在以后看到一种特殊情况)。 根据我们的类比,每个老师也有一个邮箱。 教师必须检查邮箱并处理消息。 在Actor世界中,情况恰恰相反–邮箱,当有机会时,可以使用Actor完成其工作。

此外,邮箱还有一个队列以FIFO方式存储和处理消息-与我们的常规收件箱稍有不同,在常规收件箱中,最新的是顶部的收件箱。

现在,调度员

Dispatcher做一些非常酷的事情。 从外观上看,Dispatcher只是从ActorRef获取消息并将其传递到邮箱。 但是幕后发生了一件令人惊奇的事情:

分派器包装ExecutorService (ForkJoinPool或ThreadPoolExecutor)。 它针对此ExecutorService执行MailBox

从Dispatcher中查看以下片段:

protected[akka] override def registerForExecution(mbox: Mailbox, ...): Boolean = {  
    ...
    try {
        executorService execute mbox
    ...
}

什么? 您只是说要执行邮箱吗?

对。 我们已经看到邮箱将所有消息保存在队列中。 另外,由于执行程序运行MailBox ,因此邮箱必须是Thread 你是对的。 这几乎是MailBox的声明和构造函数。

这是邮箱的签名:

private[akka] abstract class Mailbox(val messageQueue: MessageQueue) extends SystemMessageQueue with Runnable

教师演员

Akka笔记–演员信息– 1_第6张图片

MailBox触发其run方法时,会将其从消息队列中出队,然后将其传递给Actor进行处理。

将消息tell ActorRef时最终被调用的方法是目标Actor的receive方法。

TeacherActor是一个基本类,它具有引号List以及很明显的处理消息的receive方法。

看一下这个 :

教师演员

package me.rerun.akkanotes.messaging.firenforget

import scala.util.Random

import akka.actor.Actor  
import me.rerun.akkanotes.messaging.protocols.TeacherProtocol._

/*
 * Your Teacher Actor class. 
 * 
 * The class could use refinement by way of  
 * using ActorLogging which uses the EventBus of the Actor framework
 * instead of the plain old System out
 * 
 */

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)

    }

  }

}

TeacherActor的接收方法模式仅与一条消息匹配QuoteRequest (实际上,对默认情况进行模式匹配是一种很好的做法,但是有一个有趣的故事要讲)

接收方法所做的就是

  1. QuoteRequest模式匹配
  2. 从静态报价单中选择随机报价
  3. 构造QuoteResponse
  4. 将QuoteResponse打印到控制台

  • 整个项目可以从github此处下载。

我们将在接下来的部分中介绍更多有趣的内容……

翻译自: https://www.javacodegeeks.com/2014/09/akka-notes-actor-messaging-1.html

你可能感兴趣的:(队列,java,python,人工智能,spring)