Scala 阿克卡中Actorref.tell和inbox.send的区别

Scala 阿克卡中Actorref.tell和inbox.send的区别,scala,akka,Scala,Akka,因此,我开始学习Akka,并在typesafe中尝试这些示例。 因此,Hello Akka应用程序具有以下代码: import akka.actor.{ ActorRef, ActorSystem, Props, Actor, Inbox } import scala.concurrent.duration._ case object Greet case class WhoToGreet(who: String) case class Greeting(message: String

因此,我开始学习Akka,并在typesafe中尝试这些示例。 因此,Hello Akka应用程序具有以下代码:

    import akka.actor.{ ActorRef, ActorSystem, Props, Actor, Inbox }
import scala.concurrent.duration._

case object Greet
case class WhoToGreet(who: String)
case class Greeting(message: String)

class Greeter extends Actor {
  var greeting = ""

  def receive = {
    case WhoToGreet(who) => greeting = s"hello, $who"
    case Greet           => sender ! Greeting(greeting) // Send the current greeting back to the sender
  }
}

object HelloAkkaScala extends App {

  // Create the 'helloakka' actor system
  val system = ActorSystem("helloakka")

  // Create the 'greeter' actor
  val greeter = system.actorOf(Props[Greeter], "greeter")

  // Create an "actor-in-a-box"
  val inbox = Inbox.create(system)

  // Tell the 'greeter' to change its 'greeting' message
  greeter.tell(WhoToGreet("akka"), ActorRef.noSender)

  // Ask the 'greeter for the latest 'greeting'
  // Reply should go to the "actor-in-a-box"
  inbox.send(greeter, Greet)

  // Wait 5 seconds for the reply with the 'greeting' message
  val Greeting(message1) = inbox.receive(5.seconds)
  println(s"Greeting: $message1")

  // Change the greeting and ask for it again
  greeter.tell(WhoToGreet("typesafe"), ActorRef.noSender)
  inbox.send(greeter, Greet)
  val Greeting(message2) = inbox.receive(5.seconds)
  println(s"Greeting: $message2")

  val greetPrinter = system.actorOf(Props[GreetPrinter])
  // after zero seconds, send a Greet message every second to the greeter with a sender of the greetPrinter
  system.scheduler.schedule(0.seconds, 1.second, greeter, Greet)(system.dispatcher, greetPrinter)

}

// prints a greeting
class GreetPrinter extends Actor {
  def receive = {
    case Greeting(message) => println(message)
  }
}
现在我陷入了理解两者之间的区别

greeter.tell(WhoToGreet("akka"), ActorRef.noSender)

据我所知,演员在故事的结尾开始了自己的故事

val inbox = Inbox.create(system)

有人能解释一下Actorref.tell到底做了什么,然后Inbox.send行到底实现了什么

当您执行以下操作时,您直接与
ActorRef

greeter.tell(WhoToGreet("akka"), ActorRef.noSender)
另一方面,当你使用
收件箱时
,你处理的不是一个演员,而是一个演员。当您不想创建自己的参与者,但仍然希望与其他参与者异步交互时,这一点非常有用。请看

收件箱是一个类似于参与者的对象,可以从外部进行查询。它包含一个参与者,该参与者的引用可以像往常一样传递给其他参与者,并且它可以监视其他参与者的生命周期


参与者在线程池上运行(使用调度程序配置)。您可以通过配置或在代码中输入参与者用于执行的调度程序来决定

告诉的目的,也表示为
是向参与者发送消息。当参与者通过消息传递进行通信时,
tell
是用于支持该消息传递的机制。它与调用者是异步的,因此一旦调用者调用
tell
,它们就与目标参与者实例接收和处理该消息的过程分离。在这个特定的示例中,代码使用tell使迎宾参与者更新其内部状态。由于此交互不会导致任何类型的响应(接收参与者没有将消息发送回发送者以响应此请求),
tell
在这里就足够了

为了从问候者那里得到问候的回应,互动略有不同。在这种交互中,发送方希望收到响应消息。这种类型的请求/响应交互可以通过
ask
(即
)进行,在这种交互中,调用者获得一个
未来的
,当接收者回复时将完成,但此处未使用
ask
。在本例中,编码人员通过使用
收件箱
获得请求/响应语义,该收件箱可以充当参与者,从而消除了对未来的需求。对于接收者来说,收件箱必须看起来像一个
ActorRef
,允许其使用以下行将响应发送回收件箱:

sender ! Greeting(greeting)

sender()
方法返回当前正在处理的消息中发送的人的
ActorRef
收件箱
必须能够将自己表示为一个
ActorRef
,这样才能工作。但正如我前面所说,您也可以在这里使用
ask
来实现请求/响应交互。我认为这只是选择的问题。底线是,
tell
用于fire-and-forget交互模型,当需要请求/响应语义时,可以使用收件箱(或其他参与者或
ask
)。

这是否意味着如果我注释掉“inbox.send(greater,Greet)”呼叫,我仍然会看到“receive”方法在Greeter actor类@SomBhattacharyya中被调用,在该示例中,
receive
partial函数将被调用两次;一个来自
WhoToGreet
tell
,另一个来自
收件箱。发送
问候
邮件的
。如果注释掉收件箱中的
send
,则
receive
只会对
whotoreet
消息调用一次。
sender ! Greeting(greeting)