Использование фьючерсов в Акках

Я только начинаю изучать Акку Актеры в Scala. Я понимаю, что сообщения, полученные Актером, помещаются в очередь в почтовом ящике Актора и обрабатываются по одному. Обработка сообщений по одному, concurrency проблемы (условия гонки, взаимоблокировки) смягчаются.

Но что произойдет, если Актер создаст будущее для выполнения работы, связанной с сообщением? Поскольку будущее является асинхронным, актер может начать обработку следующих нескольких сообщений, в то время как будущее, связанное с предыдущим сообщением, все еще работает. Разве это не создало бы условия гонки? Как можно безопасно использовать фьючерсы в методе приема() Actor для выполнения длительных задач?

Ответ 1

Самый безопасный способ использования фьючерсов внутри актера - использовать только pipeTo в будущем и отправлять его результат в виде сообщения для актера (возможно, одного и того же актера).

import akka.pattern.pipe

object MyActor {

  def doItAsynchronously(implicit ec: ExecutionContext): Future[DoItResult] = { 
  /* ... */ 
  }

}

class MyActor extends Actor {

  import MyActor._    
  import context.dispatcher  

  def receive = {
    case DoIt =>
      doItAsynchronously.pipeTo(self)
    case DoItResult =>
       // Got a result from doing it
  }

}

Это гарантирует, что вы не будете мутировать какое-либо состояние внутри актера.

Ответ 2

Если вам нужно изменить состояние фьючерсов, не блокируя входящие сообщения, вам может потребоваться перепроектировать модель вашего актера. Я бы представил отдельных участников для каждой задачи, на которой вы будете использовать эти фьючерсы. В конце концов, основной задачей актера является сохранение своего состояния, не позволяя ему сбежать, тем самым обеспечивая безопасный concurrency. Определите актера для этой долговременной задачи, ответственность которой заключается только в том, чтобы позаботиться об этом.

Вместо того, чтобы заботиться о состоянии вручную, вы можете рассмотреть возможность использования akka FSM, чтобы получить более четкое представление о том, что изменится. Я предпочитаю этот подход к уродливым переменным, когда имею дело с более сложными системами.