Использование фьючерсов в Акках
Я только начинаю изучать Акку Актеры в 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, чтобы получить более четкое представление о том, что изменится. Я предпочитаю этот подход к уродливым переменным, когда имею дело с более сложными системами.