我目前在Scala代码中使用了akka Actor系统。我有一个父演员和一个儿童演员。我想要做的是在父actor发起一个List并让子actor:
i)生成新元素并将它们发送给将它们附加到列表的父级演员。 ii)随时可以访问列表元素。
我如何实现第二(ii)部分?
答案 0 :(得分:3)
您 必须 使用消息传递。在两个演员之间分享任何可变状态都违反了Akka提供的所有保证。
或者,您可以在您的子actor和父actor之间共享代理,这将使列表的更新线性化,同时允许同步读取。
答案 1 :(得分:1)
您可以选择父母可以回复披露其内部状态的特定消息。请参阅以下示例:
import scala.collection.immutable.Queue
class Parent extends Actor {
import Parent._
// TODO: start children here
override def receive: Receive = receiveElements(Queue.empty[Element])
def receiveElements(acc: Queue[Element]): Receive = {
case e@Element => context.become(receiveElements(acc :+ e))
case GetElements => sender ! acc
}
}
object Parent {
case class Element(s: String)
case object GetElements
}
请注意,通过在父级内部保留var queue
而不是使用context.become
+递归,可以实现相同的行为。
此外,没有设计一种刷新队列的方法可能会导致OOME。
答案 2 :(得分:-1)
好吧,我设法找到了解决方案。
如果在父Actor中创建变量并将其作为构造参数传递给子Actor,则如果不替换它,则此变量中的每个更改都是可见的。我将用一个错误的例子来解释一个正确的例子。
class ParentActor(/*constructors here*/) extends Actor{
val list =ListBuffer[Int](1,2)
child = new ChildActor(list //+other constructors)
list=ListBuffer[Int](1,2,3) // **wrong** child will see list=List(1,2)
list+=3 // **right** child will see list=List(1,2,3) as wanted
}
class ChildActor(list : ListBuffer[Int] /*++ otherconstructors here*/) extends Actor{
list=ListBuffer[Int](1,2,3,4) // **wrong** parent will see list=List(1,2,3)
list+=4 // **right** child will see list=List(1,2,3,4) as wanted
}