10.8 looploopWhile

有两件事阻碍我们充分使用react()reactWithin()。(在本节余下部分,涉及reactWithin()的讨论同样也适用于react())第一是递归调用。如果有多个case语句,典型情况下,要在每个case里面重复调用。第二,似乎没有什么好的方式跳出方法。第一个顾虑的答案是单例对象Actorloop()方法。第二个的答案是loopWhile()方法。

相比于在reactWithin()里递归的调用方法,可以在loop()调用里放一个对reactWithin()的调用。执行loop()方法的线程遇到reactWithin()的调用时,会放弃控制。消息到达时,任意的线程都可以继续执行适当的case语句。case语句执行完毕,线程会继续回到loop()块的顶部。这会一直继续下去。loopWhile()方法是类似的,但是只有提供的参数是有效的,它才会继续循环下去。因为loopWhile()负责处理循环,所以,可以把局部状态放到循环之外,在reactWithin()方法里访问它。这样的话,就给了我们一个两全其美的选择,既可以像receiveWithin()那样处理状态,又可以像reactWithin()那样利用来自线程池的线程。看一个在loopWhile()里使用reactWithin()的例子。

ConcurrentProgramming/Loop.scala

  1. import scala.actors._
  2. import Actor._
  3. val caller = self
  4. val accumulator = actor {
  5. var continue = true
  6. var sum = 0
  7. loopWhile(continue) {
  8. reactWithin(500) {
  9. case number : Int => sum += number
  10. case TIMEOUT =>
  11. continue = false
  12. caller ! sum
  13. }
  14. }
  15. }
  16. accumulator ! 1
  17. accumulator ! 7
  18. accumulator ! 8
  19. receiveWithin(1000) { case result => println("Total is " + result) }

上面的代码没有任何递归调用——这是由loopWhile()处理的。在退出消息处理的地方,只需简单的设置标记,由它处理退出循环,进而退出actor执行。代码输出如下:

  1. Total is 16