我是akka的新手,我想立即为一个消息列表运行一个列表akka actor,例如(我在这里使用scala):
输入
message_1
message_2
message_3
每封邮件的输出:
1
2
3
会立即运行3个akka演员将每个参数从列表传递到每个参数,我想稍后将这些结果用作List
个答案。理想情况下,我正在寻找可以让我跟随的操作:
runActorsForListAndWaitForAnswer(messagesList).map(_.toInt()).sum
我不知道这种方法是否存在,但它会有所帮助。感谢任何帮助,谢谢!
答案 0 :(得分:13)
首先,你必须放弃命令,阻止思维定势。一切都是异步的,Akka的味道最好。你永远不应该阻止,等待另一个演员的回复。相反,您可以使用Future[T]
对象并在其上应用函数。 将来完成后,将调用此函数。
让我们举一个简单的例子:你有一个SquareActor
取Int
并返回一个方格。要求回复的正确方法是:
squareActor ? 9 map {result =>
println(result) //81
}
//more code
非常重要:println
的代码块不会阻止。 更多代码将立即执行,您的回调方法将在稍后调用。
话虽如此,我们可以开始实施您的用例。如果我理解正确,你有一个演员列表和一个整数列表。您希望将每个整数发送到一个actor。这是一个伪代码:
val actors: List[ActorRef] = //...
val numbers: List[Int] = //...
val actorsWithArguments: List[(ActorRef, Int)] = actors zip numbers
val futuresOfAny: List[Future[Any]] = actorsWithArguments map { case (actor, number) => actor ? number}
val futures: List[Future[Int]] = futuresOfAny map {_.mapTo[Int]}
val futureOfAllResults: Future[List[Int]] = Future.sequence(futures)
val future: Future[Int] = futureOfAllResults map { _.sum}
我故意留下明确的类型来帮助您遵循代码。让我们一步一步走:
actorsWithArguments
是List
个元组。每个项目都包含一对演员和一条消息 - (actor1, message1)
,(actor2, message2)
,...
futuresOfAny
包含Future
actor ? number
次调用结果列表。 ?
返回Future[Any]
,因为:a)结果尚未知晓(b)Akka不知道结果的类型(回复消息)
futures
是强类型的,因为我们知道每个回复都是Int
。我们只是mapTo
Future[Any]
到Future[Int]
futureOfAllResults
使用从List[Future[Int]]
到Future[List[Int]]
的非常棒的转换。换句话说,我们只是将未来结果列表转换为包含所有项目的单个未来结果。
future
持有(将来会)您的结果。
如果您认为这是很多代码,那只是出于教育目的。链接和类型推断可以做到魔术:
val future = Future.sequence(actors zip numbers map { case (actor, number) => actor ? number} map { _.mapTo[Int]}) map { _.sum} }
最后你得到了你的结果。那么,将来会。现在,如果你想将结果发送给另一个演员,你只需说:
future map {sum => otherActor ! sum}
//or even...
future map otherActor.!
我强烈鼓励您阅读官方文档中的chapter on Futures,以便更清楚地了解这一点。