Scala 阿克卡,未来和关键部分

Scala 阿克卡,未来和关键部分,scala,concurrency,akka,future,Scala,Concurrency,Akka,Future,假设我们有一个Akka参与者,它以var的形式维护一个内部状态 class FooActor extends Actor { private var state: Int = 0 def receive = { ... } } 假设接收处理程序调用一个返回未来的操作,我们使用dispatcher作为上下文执行器对其进行映射,最后设置一个onSuccess回调来更改参与者状态 import context.dispatcher def receive = { case "Hello

假设我们有一个Akka参与者,它以
var
的形式维护一个内部状态

class FooActor extends Actor {
  private var state: Int = 0

  def receive = { ... }
}
假设接收处理程序调用一个返回未来的操作,我们使用dispatcher作为上下文执行器对其进行映射,最后设置一个
onSuccess
回调来更改参与者状态

import context.dispatcher
def receive = {
  case "Hello" => requestSomething() // asume Future[String]
    .map(_.size)
    .onSuccess { case i => state = i }
}
onSuccess
回调更改actor的状态是否线程安全,即使使用actor dispatcher作为执行上下文

不,不是(akka 2.3.4)

在这种情况下,您需要做的是向self发送一条消息来改变状态。如果您需要订购,您可以使用隐藏和成为。像这样的

import akka.actor.{Stash,Actor}
import akka.pattern.pipe
case class StateUpdate(i:int)
class FooActor extends Actor with Stash{
  private var state: Int = 0
  def receive = ready
  def ready  = {
    case "Hello" => requestSomething() // asume Future[String]
      .map(StateUpdate(_.size)) pipeTo self
      become(busy)
  } 
  def busy {
     case StateUpdate(i) => 
       state=i
       unstashAll()
       become(ready)
     case State.Failure(t:Throwable) => // the future failed
     case evt =>
       stash()   
  }
}
当然,这是一个过于简单的实现,您可能希望处理超时等问题,以避免让您的参与者陷入困境

如果您的州不需要订购担保:

case class StateUpdate(i:int)
class FooActor extends Actor with Stash{
  private var state: Int = 0
  def receive = {
    case "Hello" => requestSomething() // asume Future[String]
      .map(StateUpdate(_.size)) pipeTo self
    case StateUpdate(i) => state=i
  } 

但是参与者状态可能不是最后收到的字符串的长度

,只是为了支持Jean的回答,下面是文档中的示例:

class MyActor extends Actor {
    var state = ...
    def receive = {
        case _ =>
        //Wrongs

        // Very bad, shared mutable state,
        // will break your application in weird ways
        Future {state = NewState}
        anotherActor ? message onSuccess {
            r => state = r
        }

        // Very bad, "sender" changes for every message,
        // shared mutable state bug
        Future {expensiveCalculation(sender())}

        //Rights

        // Completely safe, "self" is OK to close over
        // and it's an ActorRef, which is thread-safe
        Future {expensiveCalculation()} onComplete {
            f => self ! f.value.get
        }

        // Completely safe, we close over a fixed value
        // and it's an ActorRef, which is thread-safe
        val currentSender = sender()
        Future {expensiveCalculation(currentSender)}
    }
}

谢谢,我在回答中添加了相关链接:)非常感谢!我一直在查看文档,但没有看到该部分。