Мертвые буквы встречаются в Акке при маршрутизации между братьями и сестрами - PullRequest
2 голосов
/ 09 июня 2019

Я пытаюсь построить модель, основанную на агентах, где часть модели включает в себя решения, транслируемые агентами. Сначала я инициализирую ровно четыре актера с отслеживающим родителем, а затем заставляю каждого из них «объявлять» свои решения в определенном порядке.

Я ожидаю, что каждый из них будет обновлять свои параметры каждый раз, когда брат заявляет о своем решении, но когда я запускаю код, показанный ниже, я получаю журналы о найденных мертвых письмах. Как сделать так, чтобы все действующие лица работали по порядку, получали все объявления от братьев и сестер и не прекращали работу до тех пор, пока не получат сообщение для объявления себя?

Основной метод:

import Member._

  val system: ActorSystem = ActorSystem("Abilene0")

  try {
    val groupMembers = Set("father", "mother", "wife", "husband")
    val group: ActorRef = system.actorOf(Group.props(groupMembers), "group")

    val father = system.actorOf(Member.props(group, generate(groupMembers)), "father")
    val mother = system.actorOf(Member.props(group, generate(groupMembers)), "mother")
    val wife = system.actorOf(Member.props(group, generate(groupMembers)), "wife")
    val husband = system.actorOf(Member.props(group, generate(groupMembers)), "husband")

    father ! Declare
    wife ! Declare
    husband ! Declare
    mother ! Declare

  } finally {
    system.terminate()
  }

1 Ответ

1 голос
/ 10 июня 2019

При просмотре вашего кода становится очевидным, что сообщения актера будут доставлены на deadletters. В вашем коде вы вызываете system.terminate() в finally блоке вашего оператора try-catch-finally, это означает, что прекращение действия системы актера произойдет сразу после вашего блока try, что немедленно остановит всех участников. Однако вы должны знать, что Актеры общаются с помощью асинхронных сообщений . Это означает, что даже после того, как ваш код try-block завершен, в ваших акторах могут выполняться различные фоновые задачи, пока все актеры не остановятся.

Позвольте мне создать сценарий:

class Handler extends Actor with ActorLogging{
  override def receive: Receive = {
    case "START" =>
      println("Test Started.")
  }
}

class Tester(handler: ActorRef) extends Actor with ActorLogging{
  override def receive: Receive = {
    case "TEST" =>
      println("Test started.")
      // Here, when handler actor stops when system.terminate() occur, "START" message
      // will be no longer delivered to actor handler instead delivered to deadletters.
      1 to 1000 foreach ( _ => {
        handler ! "START"
      })
  }
}

val system: ActorSystem = ActorSystem("test")
val handler = system.actorOf(Props(new Handler), "handler")
val tester = system.actorOf(Props(new Tester(handler)), "tester")
try {
  tester ! "TEST"
} finally {
  system.terminate()
}

В приведенном выше коде, когда вызывается system.terminate(), handler актер останавливается, а затем tester актер останавливается. Однако до того, как tester субъект будет остановлен, все еще может быть сообщение "START", отправляемое handler субъекту. Однако handler субъект уже остановлен, это сообщение "START" больше не будет доставляться на handler и, следовательно, доставляться на deadletters.

Следовательно, в вашем коде после выполнения system.terminate() все ваши акторы - group, father, mother, wife и husband немедленно останавливаются и, следовательно, любые дальнейшие сообщения, отправляемые этим акторам почтовые ящики доставляются синтетическому актеру deadletters.

Как мне убедиться, что все актеры работают по порядку, получить все декларации от братьев и сестер и не прекращать, пока они не получат сообщение заявить о себе?

Для этого вы можете явно передать PoisonPill сообщение каждому субъекту, который остановит субъект только после обработки всех сообщений в его почтовом ящике.

...