在尝试使用Akka演员时,我编写了一个用例并没有按预期工作。我已经定义了一个接收MyActor
消息的演员"start"
。此消息启动一个调度程序,该调度程序应该每隔"request"
将消息self
中继到1 second
。这是代码:
import akka.actor._
import scala.concurrent.Await
import scala.concurrent.duration._
import akka.pattern.gracefulStop
import scala.concurrent.ExecutionContext.Implicits.global
object ScheduledActors {
def main(args: Array[String]) {
implicit val system = ActorSystem("ScheduledActors")
val admin = system.actorOf(Props[MyActor], name = "my-actor")
admin ! "start"
val adminFuture = gracefulStop(admin, 2 minutes)
Await.result(adminFuture, 2 minutes)
}
class MyActor extends Actor {
var cancellableOption: Option[Cancellable] = None
def receive = {
case "start" =>
println("start")
cancellableOption =
Some(context.system.scheduler.schedule(0 seconds, 1 second) { self ! "request" })
case "request" =>
println("request")
case "stop" =>
println("stop")
cancellableOption match {
case None => // no-op
case Some(v) => v.cancel()
}
context.stop(self)
}
}
}
我尝试了一些变种。将schedule
方法变体与明确的ActorRef
和message
结合使用。 E.g:
schedule(initialDelay: Duration, frequency: Duration, receiver: ActorRef, message: Any): Cancellable
在每种情况下,演员都不会收到"request"
消息。这个块肯定被调用,因为我已经使用println
语句进行了验证,作为一个完整性检查。但交付是不行的。
这使我认为self
引用在此上下文中实际执行时可能不会提供相同的上下文(例如,ForkJoinPool调用)。 Akka文档确实警告不要在调度调用的上下文中使用不稳定的引用。但是self
作为接收者被明确引用为reasonable alternative。
此时我在这里有点不知所措。任何帮助是极大的赞赏。
答案 0 :(得分:1)
这是因为演员已被终止。在运行时,您应该看到记录死信,例如:
[INFO] [04/08/2014 17:05:03.903] [ScheduledActors-akka.actor.default-dispatcher-2] [akka:// ScheduledActors / user / my-actor]消息[java.lang。字符串]从Actor [akka:// ScheduledActors / user / my-actor#-1824493491]到Actor [akka:// ScheduledActors / user / my-actor#-1824493491]未送达。 [1]遇到死信。可以使用配置设置关闭或调整此日志记录' akka.log-dead-letters'和' akka.log-dead-letters-during-shutdown'。
GracefulStop不了解您已完成的计划并停止该actor,因为邮箱为空。 如果要将main方法更改为以下内容,则应该看到消息:
implicit val system = ActorSystem("ScheduledActors")
val admin = system.actorOf(Props[MyActor], name = "my-actor")
admin ! "start"
Thread.sleep(5000)
admin ! "stop"