Scala 阿克卡,未来和关键部分
假设我们有一个Akka参与者,它以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
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)}
}
}
谢谢,我在回答中添加了相关链接:)非常感谢!我一直在查看文档,但没有看到该部分。