scala - Akka中Actorref.tell和inbox.send的区别

标签 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)

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)


inbox.send(greeter, Greet)

根据我的理解, Actor 在结束时开始自己的线程
val inbox = Inbox.create(system)

有人可以解释一下 Actorref.tell 究竟做了什么,然后 Inbox.send 行究竟实现了什么。

最佳答案

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

为了从迎宾员那里获得问候语响应,交互略有不同。在此交互中,发送方期待响应消息。这种类型的请求/响应交互可以通过 ask 处理(即 ? ),其中调用者获得 Future当接收者回复但 ask 时,将完成返回这里没有使用。在此示例中,编码器通过使用 Inbox 获得请求/响应语义。相反,它可以充当 Actor ,并且消除了对 future 的需要。收件箱必须看起来像 ActorRef到接收器,允许它使用以下行将响应路由回它:

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

关于scala - Akka中Actorref.tell和inbox.send的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27381815/

相关文章:

akka - 使用 Akka HTTP(正式名称为 Spray)的 GET 请求的查询参数

scala - 在 Akka 中设置日志记录级别

scala - 如何让虚拟时间在猫效应 3 的测试中通过?

scala - akka 流 throttle 如何工作?

generics - 在 Scala 中模拟可变参数模板

java - 语义分析时如何处理多个源文件?

java - 如何向非 Actor 世界公开 Akka Actor 的不可变消息?

scala - 将 RX Observable 传递给 Actor (scala)是否安全?

java - Scala: "val"作为标识符可能吗?链接到 java 库需要它

unit-testing - 在 ScalaTest 中 `should` 、 `can` 、 `must` 之间有什么区别