让演员入睡

时间:2013-10-30 05:13:29

标签: multithreading scala akka actor

我想让一个演员睡一会儿,特别是它应该根据条件决定是否要自己

class MyActor extends Actor {
  def receive {
    case "doWork" => doWork()
  }

  def doWork(): Unit = {
    // doing some work
    val condition = calculateCondition
    if (condition) {
      // sleep for 5 seconds
      // Thread.sleep(5000) 
    }
  }
}

我非常确定在演员中调用Thread.sleep(5000)并不应该是另一种方式。因此,我该如何让它睡觉?

1 个答案:

答案 0 :(得分:8)

我希望使用Actor的状态/行为更改来执行此操作。 Akka为您提供了两种方法:您可以实现一个完整的状态机,或者使用context.become(并混合在akka.actor.Stash中),并让actor传递(调度)消息对自己。对于这种情况,前者感觉有些过分,所以这就是我要编写代码的方式:

import akka.actor._    
import scala.concurrent.duration._

class MySleepyActor(duration: FiniteDuration = (5 seconds)) extends Actor with Stash {

  import context._

  override def preStart() { become(running) }

  def receive = PartialFunction.empty

  def running: Actor.Receive = {
    case "doWork" =>       
      if (doWork()) {
        scheduleReactivate
        become(paused)
      }
    case "wakeUp" => // already awake
  }

  def paused: Actor.Receive = {
    case "doWork" => stash()
    case "wakeUp" => 
      unstashAll()
      become(running)
  }

  def scheduleReactivate: Unit = {
    system.scheduler.scheduleOnce(duration, self, "wakeUp")
  }

  def doWork(): Boolean = {
    // doing some work, then:
    calculateCondition
  }
}

注意:我没有测试过这段代码!但是,应该给你一些合意的想法。