正如评论中所说,标准Actor库Combinatiors.loop
旨在使您免于在重复执行Actor主体时出现堆栈溢出。
消息处理实际上[几乎]总是被安排在专用线程池中执行时,将loop
用于事件驱动的参与者(react
)有什么意义吗?身体的简单递归调用似乎是一个更有效的选择。
方法 Reactor.seq
(由 Combinatiors.loop
调用)定义如下:
private[actors] def seq[a, b](first: => a, next: => b): Unit = {
val killNext = this.kill
this.kill = () => {
this.kill = killNext
// to avoid stack overflow:
// instead of directly executing `next`,
// schedule as continuation
scheduleActor({ case _ => next }, null)
throw Actor.suspendException
}
first
throw new KillActorControl
}
假设next
是直接调用的。在这种情况下,将立即执行react
,计划消息处理,并挂起执行组件。没有空间容纳堆栈溢出...
我错在哪里?
loop
是一个通用构造,可用于基于线程和事件驱动的参与者。如果您尝试递归处理基于线程的参与者的消息,您将很快导致堆栈溢出(除非您的消息处理是尾递归的,并且可以优化)。
关于事件驱动的参与者,你是绝对正确的 - 递归处理将更有效,只要特定于基于线程的参与者的堆栈溢出场景对事件驱动的参与者无效(你甚至不应该使递归可优化)。