8

是否可以Actor等待 X 秒来接收任何消息,如果收到消息,则照常处理,否则将消息发送给其他Actor人(在构造函数中预先确定)?

4

3 回答 3

18

有可能,看看Akka Actor "ask" 和 "Await" with TimeoutException。但请记住,在 Actor 内部进行阻塞是一个非常糟糕的主意,因为在此期间 Actor 无法处理任何其他消息。此外,它阻塞了一个 Akka 处理线程。

更好的方法是发送消息(即发即弃)并使用Akka 调度程序安排一些超时事件。当响应到达时,取消该事件或设置一些标志,以便在响应确实准时到达时不会触发。

于 2012-10-05T06:46:29.033 回答
5

是的,如果你想等待任何消息,你只需设置一个receiveTimeouthttp ://doc.akka.io/docs/akka/current/scala/actors.html#receive-timeout

(这里的文档有点误导,您也可以在每条消息后设置receiveTimeout)

于 2012-10-05T21:07:18.357 回答
4

可能有点矫枉过正,但您可以查看有限状态机 (FSM)特征。

import akka._
import actor._
import util._
import duration._
import Impatient._

object Impatient {
  sealed trait State
  case object WaitingForMessage extends State
  case object MessageReceived extends State
  case object TimeoutExpired extends State

  sealed trait Data
  case object Unitialized extends Data

  // In
  case object Message
}

class Impatient(receiver: ActorRef) extends Actor with FSM[State, Data] {
  startWith(WaitingForMessage, Unitialized)

  when(WaitingForMessage, stateTimeout = 3 seconds) {
    case Event(StateTimeout, data) => goto(TimeoutExpired) using data // data is usually modified here
    case Event(Message, data) => goto(MessageReceived) using data // data is usually modified here
  }

  onTransition {
    case WaitingForMessage -> MessageReceived => stateData match {
      case data => log.info("Received message: " + data)
    }
    case WaitingForMessage -> TimeoutExpired => receiver ! TimeoutExpired
  }

  when(MessageReceived) {
    case _ => stay
  }

  when(TimeoutExpired) {
    case _ => stay
  }

  initialize
}

这是在行动:

object Main extends App {
  import akka._
  import actor._
  import Impatient._

  val system = ActorSystem("System")

  val receiver = system.actorOf(Props(new Actor with ActorLogging {
    def receive = {
      case TimeoutExpired => log.warning("Timeout expired")
    }
  }))

  val impatient = system.actorOf(Props(new Impatient(receiver)), name = "Impatient")
  impatient ! Message

  val impatient2 = system.actorOf(Props(new Impatient(receiver)), name = "Impatient2")
  Thread.sleep(4000)
  impatient2 ! Message

  system.shutdown()
}
于 2012-10-05T07:25:03.123 回答