我没有得到两个“表达式”之间的实际(语义)差异 据说“循环”适合“反应”和“而(真实)”适合“接收”,因为“反应”不会返回,“循环”是一个再次调用身体的功能(至少这是我从消息来源中扣除了什么 - 我对使用过的“andThen”并不熟悉。 “接收”阻止池中的一个线程,“反应”不会。但是,对于“反应”,查找可以附加功能的线程。
所以问题是:为什么我不能用“接收”来使用“循环”?它似乎与“while(true)”变体的行为不同(并且更好!),至少这是我在分析器中观察到的。 更奇怪的是,使用“-Dactors.maxPoolSize = 1 -Dactors.corePoolSize = 1”并使用“while(true)”和“receive”块立即调用乒乓(这是我所期望的) - 但是,“循环“和”接收“,它没有问题 - 在一个线程中 - 这是怎么回事?
谢谢!
答案 0 :(得分:4)
while
和loop
之间的关键区别在于while
限制循环迭代 在同一个帖子中发生。 loop
构造(由 Daniel 描述)使actor子系统能够在它选择的任何线程上调用 react 。
因此,在receive
中使用while (true)
的组合将一个actor绑定到一个线程。使用loop
和react
可以在单个帖子上运行支持多个角色。
答案 1 :(得分:2)
方法loop
在对象Actor
中定义:
private[actors] trait Body[a] {
def andThen[b](other: => b): Unit
}
implicit def mkBody[a](body: => a) = new Body[a] {
def andThen[b](other: => b): Unit = self.seq(body, other)
}
/**
* Causes <code>self</code> to repeatedly execute
* <code>body</code>.
*
* @param body the code block to be executed
*/
def loop(body: => Unit): Unit = body andThen loop(body)
这很令人困惑,但会发生的事情是循环之后的块({
和}
之间的东西)作为第一个参数传递给方法seq
,并且带有该块的新循环作为第二个参数传递。
对于方法seq
,在特征Actor
中,我们发现:
private def seq[a, b](first: => a, next: => b): Unit = {
val s = Actor.self
val killNext = s.kill
s.kill = () => {
s.kill = killNext
// to avoid stack overflow:
// instead of directly executing `next`,
// schedule as continuation
scheduleActor({ case _ => next }, 1)
throw new SuspendActorException
}
first
throw new KillActorException
}
因此,新的循环被安排在kill之后的下一个动作,然后块被执行,然后抛出类型KillActorException的异常,这将导致循环再次执行。
因此,while
循环执行速度比loop
快得多,因为它不会抛出任何异常,也不执行调度等。另一方面,调度程序有机会在其间安排其他内容。两次执行loop
。