1

我很好奇是否可以在不使用 var 来保持实例的情况下安全地实现自取消轮询器akka.actor.Cancellable

到目前为止,我想出了类似于您在下面的示例中看到的内容。但是,我很好奇是否可以安全地假设在热交换发生之前永远不会发送“tick”消息,即调度轮询器的行:

tick(1, 5, context.system.scheduler.schedule(Duration.Zero, 3 seconds, self, "tick"))

基本上是一样的:

val poll = context.system.scheduler.schedule(Duration.Zero, 3 seconds, self, "tick")
tick(1, 5, poll)

所以,我认为在某些情况下,会在热插拔有机会发生之前收到第一个滴答声……想法?

import akka.actor.{Cancellable, ActorSystem}
import akka.actor.ActorDSL._
import concurrent.duration._

object PollerDemo {
  def run() {
    implicit val system = ActorSystem("DemoPoller")
    import system.dispatcher

    actor(new Act{
      become {
        case "tick" => println("UH-OH!")
        case "start" =>
          become {
            tick(1, 5, context.system.scheduler.schedule(Duration.Zero, 3 seconds, self, "tick"))
          }
      }
      def tick(curr:Long, max:Long, poll:Cancellable):Receive = {
        case "tick" => {
          println(s"poll $curr/$max")
          if(curr > max)
            cancel(poll)
          else
            become{ tick(curr + 1, max, poll) }
        }
      }
      def cancel(poll:Cancellable) {
        println("cancelling")
        poll.cancel()
        println(s"cancelled successfully? ${poll.isCancelled}")
        println("shutting down")
        context.system.shutdown()
      }
    }) ! "start"

    system.awaitTermination(1 minute)
  }
}
4

2 回答 2

3

我的猜测是你的代码会好的。请记住,演员一次只能处理一个邮箱。当您收到start消息时,您设置了一个计时器,它将向邮箱传递另一条消息,然后您交换接收实现。因为您在处理start消息时进行了接收交换,所以在处理邮箱中的下一条消息之前,您已经更改了参与者的接收行为。因此,当它继续处理tick消息时,您可以确定它将使用新的接收行为。

您可以通过在第一个内部发送附加tick消息来验证这一点,become如下所示:

become {
  self ! "tick"
  tick(1, 5, context.system.scheduler.schedule(Duration.Zero, 3 seconds, self, "tick"))
}

在这里,当询问在成为块期间发送的消息是否将由旧接收或新接收处理时,我们实际上从等式中消除了计时器。我没有运行它,但是根据我的理解或 akka,这两个滴答声都应该由新的接收处理。

于 2013-06-16T10:59:53.350 回答
1

你真的不能用演员做纯粹的函数式编程。向他们发送消息是一种副作用。由于他们的接收函数不返回结果,所以当接收到消息时,actor 所能做的就是产生副作用。几乎你的代码所做的每一件事都是为了副作用

您可能会在代码实现中避免使用 var,但become会在 Actor 超类中更改 var。 context.system.scheduler.schedule显然是某处的副作用和变异状态。所做的每一件事cancel都是副作用。 system.awaitTermination(1 minute)不是函数...

于 2013-06-16T00:33:17.933 回答