10.8 loop
和loopWhile
有两件事阻碍我们充分使用react()
和reactWithin()
。(在本节余下部分,涉及reactWithin()
的讨论同样也适用于react()
)第一是递归调用。如果有多个case
语句,典型情况下,要在每个case
里面重复调用。第二,似乎没有什么好的方式跳出方法。第一个顾虑的答案是单例对象Actor
的loop()
方法。第二个的答案是loopWhile()
方法。
相比于在reactWithin()
里递归的调用方法,可以在loop()
调用里放一个对reactWithin()
的调用。执行loop()
方法的线程遇到reactWithin()
的调用时,会放弃控制。消息到达时,任意的线程都可以继续执行适当的case
语句。case
语句执行完毕,线程会继续回到loop()
块的顶部。这会一直继续下去。loopWhile()
方法是类似的,但是只有提供的参数是有效的,它才会继续循环下去。因为loopWhile()
负责处理循环,所以,可以把局部状态放到循环之外,在reactWithin()
方法里访问它。这样的话,就给了我们一个两全其美的选择,既可以像receiveWithin()
那样处理状态,又可以像reactWithin()
那样利用来自线程池的线程。看一个在loopWhile()
里使用reactWithin()
的例子。
ConcurrentProgramming/Loop.scala
import scala.actors._
import Actor._
val caller = self
val accumulator = actor {
var continue = true
var sum = 0
loopWhile(continue) {
reactWithin(500) {
case number : Int => sum += number
case TIMEOUT =>
continue = false
caller ! sum
}
}
}
accumulator ! 1
accumulator ! 7
accumulator ! 8
receiveWithin(1000) { case result => println("Total is " + result) }
上面的代码没有任何递归调用——这是由loopWhile()
处理的。在退出消息处理的地方,只需简单的设置标记,由它处理退出循环,进而退出actor执行。代码输出如下:
Total is 16