Подтвердить что ты не робот

Акка в Scala, восклицательный знак и знак вопроса

В чем разница между восклицательным знаком (!) и вопросительным знаком (?) при отправке сообщений Актерам?

myActor ! new hello(value1)
myActor ? new hello(value1)
4b9b3361

Ответ 1

Бесстыдно скопировано [awesome] официальный документ (посмотрите еще Отправить сообщения):

Сообщения отправляются актеру одним из следующих способов.

! означает "огонь и забыть", например. отправить сообщение асинхронно и немедленно возвращайтесь. Также известен как tell.

? отправляет сообщение асинхронно и возвращает a Future, представляющий возможный ответ. Также известен как ask.

Ответ 2

С точки зрения получателя он видит сообщения tell и ask одинаково. Однако при приеме tell значение sender будет ссылкой для актера, который отправил сообщение, тогда как для ask, sender настроен таким образом, что любой ответ отправляется в созданный Future в актере, который сделал запрос.

В ask есть преимущество, что легко понять, что ответ, который вы получаете, определенно является результатом сообщения, которое вы задавали, тогда как с помощью Tell вам может потребоваться использовать уникальные идентификаторы для достижения аналогичного результат. Однако с ask вам нужно установить timeout, после которого Future завершится с ошибкой, если ответ не получен.

В приведенном ниже коде тот же эффект достигается с помощью tell и ask.

import akka.actor.{Props, Actor}
import scala.concurrent.duration._
import akka.pattern.ask

class TellActor extends Actor {

  val recipient = context.actorOf(Props[ReceiveActor])

  def receive = {
    case "Start" =>
      recipient ! "Hello" // equivalent to recipient.tell("hello", self)

    case reply => println(reply)
  }
} 

class AskActor extends Actor {

  val recipient = context.actorOf(Props[ReceiveActor])

  def receive = {
    case "Start" =>
      implicit val timeout = 3 seconds
      val replyF = recipient ? "Hello" // equivalent to recipient.ask("Hello")
      replyF.onSuccess{
        case reply => println(reply)
      }
  }
}

class ReceiveActor extends Actor {

  def receive = {
    case "Hello" => sender ! "And Hello to you!"
  }
}