简体   繁体   English

如何在不使用var的情况下实现自动取消轮询?

[英]How to implement a self-cancelling poller without using a var?

I'm curious if it's possible to safely implement a self-cancelling poller without using a var to keep the instance of akka.actor.Cancellable 我很好奇是否可以安全地实现自动取消轮询器而不使用var来保持akka.actor.Cancellable的实例

So far, I came up with something like what you see in the example below. 到目前为止,我提出了类似于下面示例中所示的内容。 However, I'm curious if it's safe to assume that the "tick" message will never be dispatched before the hotswap happens , ie the line that schedules the poller: 但是, 我很好奇是否可以安全地假设在hotswap发生之前永远不会调度“tick”消息 ,即调度轮询器的行:

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

is basically the same as: 基本相同:

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

So, I would think that in some cases the first tick would be received before the hotswap has a chance to happen... Thoughts? 所以,我认为在某些情况下,在热交换有机会发生之前会收到第一个滴答声......思考?

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)
  }
}

My guess is that your code will be okay. 我的猜测是你的代码没问题。 Remember, actors only process their mailbox one at a time. 请记住,演员一次只能处理一个邮箱。 When you receive the start message, you setup a timer that will deliver another message to the mailbox and then you swap the receive implementation. 当您收到start消息时,您设置了一个计时器,它将向邮箱传递另一条消息,然后您交换接收实现。 Because you do the receive swap while you are still processing the start message, then you will have already changed the actors's receive behavior before it processes the next message in the mailbox. 因为在处理start消息时执行接收交换,所以在处理邮箱中的下一条消息之前,您已经更改了actor的接收行为。 So when it moves on to process the tick message you can be sure that it will be using the new receive behavior. 因此,当它继续处理tick消息时,您可以确定它将使用新的接收行为。

You could verify this by sending an additional tick message inside the first become like so: 你可以通过发送一个额外的验证此tick内的第一条消息become像这样:

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

Here we are really eliminating the timer from the equation when asking if a message sent during the become block will be processed by the old receive or the new receive. 这里我们确实从等式中消除了计时器,当询问在成为块期间发送的消息是否将由旧接收或新接收处理时。 I did not run this, but from my understanding or akka, both of these ticks should be handled by the new receive. 我没有运行这个,但根据我的理解或akka,这两个滴答应该由新的接收处理。

You really can't do pure functional programming with actors. 你真的不能用演员做纯函数式编程。 Sending them messages is a side-effect. 发送消息是一种副作用。 Since their receive function doesn't return a result, all the actor can do when receiving a message is to side effect. 由于它们的接收函数不返回结果,所有演员在接收消息时都可以做到副作用。 Just about every single thing your code does is for side-effects 几乎你的代码所做的每一件事都是副作用

You might be avoiding vars in your implementation of the code, but become is mutating a var in the Actor superclass. 您可能在代码实现中避免使用变量,但是become在Actor超类中变量变量。 context.system.scheduler.schedule is clearly side-effecting and mutating state somewhere. context.system.scheduler.schedule显然是副作用并在某处改变状态。 Every single thing that cancel does is a side effect. cancel每一件事都是副作用。 system.awaitTermination(1 minute) is not a function... system.awaitTermination(1 minute)不是函数...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM