我正在尝试通过网络设置心跳,即让演员在固定的时间段内向网络发送消息。我想知道你是否有比我下面使用的更好的解决方案,因为我觉得非常难看,考虑到同步限制。
import akka.actor._
import akka.actor.Actor
import akka.actor.Props
import akka.actor.ScalaActorRef
import akka.pattern.gracefulStop
import akka.util._
import java.util.Calendar
import java.util.concurrent._
import java.text.SimpleDateFormat
import scala.Array._
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
sealed trait Message
case class Information() extends Message//does really need to be here?
case class StartMessage() extends Message
case class HeartbeatMessage() extends Message
case class StopMessage() extends Message
case class FrequencyChangeMessage(
f: Int
) extends Message
class Gps extends Actor {
override def preStart() {
val child = context.actorOf(Props(new Cadencer(500)), name = "cadencer")
}
def receive = {
case "beat" =>
//TODO
case _ =>
println("gps: wut?")
}
}
class Cadencer(p3riod: Int) extends Actor {
var period: Int = _
var stop: Boolean = _
override def preStart() {
period = p3riod
stop = false
context.system.scheduler.scheduleOnce(period milliseconds, self, HeartbeatMessage)
}
def receive = {
case StartMessage =>
stop = false
context.system.scheduler.scheduleOnce(period milliseconds, self, HeartbeatMessage)
case HeartbeatMessage =>
if (false == stop) {
context.system.scheduler.scheduleOnce(0 milliseconds, context.parent, "beat")
context.system.scheduler.scheduleOnce(period milliseconds, self, HeartbeatMessage)
}
case StopMessage =>
stop = true
case FrequencyChangeMessage(f) =>
period = f
case _ =>
println("wut?\n")
//throw exception
}
}
object main extends App {
val system = akka.actor.ActorSystem("mySystem")
val gps = system.actorOf(Props[Gps], name = "gps")
}
我在此处调用的cadencer
会向目标actor
发送一个HeartbeatMessage
;在给定的时间之后发送订单以重新发送一个订单,从而继续进行StopMessage
(将stop
翻转到true
)。好?
是否有一个独立的actor
效率而不是更大的一个?
答案 0 :(得分:1)
试试这个。它不需要单独的cadencer类。
class Gps extends Actor
{
var ticker : Cancellable = _
override def preStart()
{
println ("Gps prestart")
// val child = context.actorOf(Props(new Cadencer(500)), name = "cadencer")
ticker = context.system.scheduler.schedule (
500 milliseconds,
500 milliseconds,
context.self,
"beat")
}
def receive: PartialFunction[Any, Unit] =
{
case "beat" =>
println ("got a beat")
case "stop" =>
ticker.cancel()
case _ =>
println("gps: wut?")
}
}
object main extends App
{
val system = akka.actor.ActorSystem("mySystem")
val gps = system.actorOf(Props[Gps], name = "gps")
Thread.sleep (5000)
gps ! "stop"
println ("stop")
}
答案 1 :(得分:0)
演员非常轻量级,所以让一个演员发送心跳消息是没有问题的(如果你想到单一责任原则,它更可取。)
进一步评论:
如果你想摆脱期间变量,你可以做以下事情(它被称为hotswapping):
override def preStart() {
// ...
context.become(receive(p3riod))
}
def receive(period: Int) = {
// ...
case FrequencyChangeMessage(f) =>
context.become(receive(f))
// ...
}
您可以在获取StopMessage后停止actor,而不是使用stop var。 如果你再次需要一个心跳演员,那就开始一个新的。
您可以将消息直接发送给父级,而不是使用0毫秒进行调度。