我有一个ActorA,它从输入流中读取并向一组ActorB发送消息。当ActorA到达输入流的末尾时,它会清理其资源,向ActorB广播一个Done消息,并自行关闭。
我有大约12个ActorB发送消息给一组ActorC&#39。当ActorB收到来自ActorA的Done消息时,它会清理其资源并关闭自己,除了最后幸存的ActorB,它在关闭自己之前向ActorC广播一个Done消息。
我有大约24个ActorC发送消息到单个ActorD。与ActorB相似,当每个ActorC获得Done消息时,它会清理其资源并自行关闭,除了最后幸存的ActorC向ActorD发送Done消息。
当ActorD获得Done消息时,它会清理其资源并自行关闭。
最初我有ActorB&,并且ActorC在收到它时立即传播Done消息,但这可能导致ActorC在所有ActorB&之前关闭已经完成了他们的队列处理;同样,在ActorC处理完队列之前,ActorD可能会关闭。
我的解决方案是使用在ActorB&#39>之间共享的AtomicInteger
class ActorB(private val actorCRouter: ActorRef,
private val actorCount: AtomicInteger) extends Actor {
private val init = {
actorCount.incrementAndGet()
()
}
def receive = {
case Done => {
if(actorCount.decrementAndGet() == 0) {
actorCRouter ! Broadcast(Done)
}
// clean up resources
context.stop(self)
}
}
}
ActorC使用类似的代码,每个ActorC共享一个AtomicInteger。
目前,所有参与者都是在一个Web服务方法中初始化的,下游的ActorRef是在上游演员中传递的。构造
是否有首选方法可以执行此操作,例如使用Akka方法而不是AtomicInteger?
编辑:我考虑以下作为一种可能的选择:当一个演员收到一个Done消息时,它将接收超时设置为5秒(程序将花费一个多小时来运行,因此延迟清理/关闭几秒钟不会影响表现);当actor获得ReceiveTimeout时,它会向下游actor广播Done,清理并关闭。 (ActorB和ActorC的路由器使用SmallestMailboxRouter)
class ActorB(private val actorCRouter: ActorRef) extends Actor {
def receive = {
case Done => {
context.setReceiveTimeout(Duration.create(5, SECONDS))
}
case ReceiveTimeout => {
actorCRouter ! Broadcast(Done)
// clean up resources
context.stop(self)
}
}
}
答案 0 :(得分:1)
在相关演员之间共享actorCount并不是一件好事。 Actor应该只使用自己的状态来处理消息。 如何为ActorB类型的actor拥有ActorBCompletionHanlder actor。所有ActorB都会引用ActorBCompletionHanlder actor。每次当ActorB收到Done消息时,它都可以进行必要的清理并简单地将完成的消息传递给ActorBCompletionHanlder。 ActorBCompletionHanlder将维持状态变量以维持计数。每次收到完成的消息,它都可以简单地更新计数器。因为这只是这个actor的状态变量,所以不需要原子,这样就不需要任何显式锁定。一旦接收到最后完成的消息,ActorBCompletionHanlder将向ActorC发送完成消息。 这样,activeCount的共享不是演员之间,而是由ActorBCompletionHanlder管理。对于其他类型,可以重复相同的事情。
A-> B's - > BCompletionHanlder - > C' - > CCompletionHandler - > d
其他方法可能是让一个监督演员与evey相关的演员组合。在监视器上使用监视api和子终止事件,您可以选择在收到上一个完成的消息后决定该做什么。
val child = context.actorOf(Props[ChildActor])
context.watch(child)
case Terminated(child) => {
log.info(child + " Child actor terminated")
}