[英]How to implement a self-cancelling poller without using a var?
我很好奇是否可以安全地实现自动取消轮询器而不使用var来保持akka.actor.Cancellable
的实例
到目前为止,我提出了类似于下面示例中所示的内容。 但是, 我很好奇是否可以安全地假设在hotswap发生之前永远不会调度“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)
}
}
我的猜测是你的代码没问题。 请记住,演员一次只能处理一个邮箱。 当您收到start
消息时,您设置了一个计时器,它将向邮箱传递另一条消息,然后您交换接收实现。 因为在处理start
消息时执行接收交换,所以在处理邮箱中的下一条消息之前,您已经更改了actor的接收行为。 因此,当它继续处理tick
消息时,您可以确定它将使用新的接收行为。
你可以通过发送一个额外的验证此tick
内的第一条消息become
像这样:
become {
self ! "tick"
tick(1, 5, context.system.scheduler.schedule(Duration.Zero, 3 seconds, self, "tick"))
}
这里我们确实从等式中消除了计时器,当询问在成为块期间发送的消息是否将由旧接收或新接收处理时。 我没有运行这个,但根据我的理解或akka,这两个滴答应该由新的接收处理。
你真的不能用演员做纯函数式编程。 发送消息是一种副作用。 由于它们的接收函数不返回结果,所有演员在接收消息时都可以做到副作用。 几乎你的代码所做的每一件事都是副作用
您可能在代码实现中避免使用变量,但是become
在Actor超类中变量变量。 context.system.scheduler.schedule
显然是副作用并在某处改变状态。 cancel
每一件事都是副作用。 system.awaitTermination(1 minute)
不是函数...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.