Мне нужен актер для отправки сообщения каждую минуту. Как мне лучше всего достичь такого поведения? Я боюсь использовать java.lang.Thread.sleep(long millis)
, поскольку поток, по-моему, может быть разделен между многими участниками в Scala.
Как написать актера таймера в Scala?
Ответ 1
Создайте актера с receiveWithin
, чтобы действовать как таймер.
Ответ 2
Или, как сказал @Daniel, вот пример:
import scala.actors._
import scala.actors.Actor._
class TimerActor(val timeout: Long,val who: Actor,val reply: Any) extends Actor {
def act {
loop {
reactWithin(timeout) {
case TIMEOUT => who ! reply
}
}
}
}
val a = actor {
loop {
react {
case x => println(x)
}
}
}
val t = new TimerActor(1000, a, "Go for it")
a.start
t.start
Ответ 3
Вы можете использовать Akka FSM для моделирования актера, который остается в состоянии ожидания forMax
миллис в состоянии ожидания, а затем отправляет сообщение, например. переключаясь в другое состояние при использовании onTransition
и оставаясь там на 0 миллисекунд, чтобы переключиться обратно в состояние ожидания. На странице akka есть хороший пример.
Ответ 4
import scala.actors._
class Wakeup[A](millis: Int, who: ReplyReactor, alarm: A) extends Thread {
val done = new java.util.concurrent.atomic.AtomicBoolean(false)
override def run {
while (!done.get()) {
who ! alarm
Thread.sleep(millis)
}
}
}
case object BEEP {}
val a = new ReplyReactor { def act { loop { react {
case BEEP => println("Wha?! "+new java.util.Date)
case _ =>
}}}}
val b = new Wakeup(60000,a,BEEP)
a.start
Зачем использовать актера, когда поток нужен вам?
scala> b.start
scala> Wha?! Mon Nov 07 18:43:18 EST 2011
Wha?! Mon Nov 07 18:44:18 EST 2011
Wha?! Mon Nov 07 18:45:18 EST 2011
Wha?! Mon Nov 07 18:46:18 EST 2011
Wha?! Mon Nov 07 18:47:18 EST 2011
Wha?! Mon Nov 07 18:48:18 EST 2011
Wha?! Mon Nov 07 18:49:18 EST 2011
Wha?! Mon Nov 07 18:50:18 EST 2011
Wha?! Mon Nov 07 18:51:18 EST 2011
Wha?! Mon Nov 07 18:52:18 EST 2011
Ответ 5
Я закончил создание специального экземпляра Runnable, который продолжает отправлять сообщение целевому игроку. Как
case class QueueTick()
class QueueWatcherActor extends Actor {
override def receive = {
case QueueTick() => // do it here
}
}
val ref = ActorSystem("xxx")
val actor = ref.actorOf(Props[QueueWatcherActor])
val executor = Executors.newSingleThreadScheduledExecutor()
executor.scheduleAtFixedRate(new Runnable {
def run() {
actor ! QueueTick()
}
},1,60,TimeUnit.SECONDS)
Ответ 6
Так как scala.actors теперь устарел и заменен актерами akka (а так как в акках акка не реагируют или не принимаются), вот как это сделать, используя акковских актеров (это на самом деле меньше "взломать", чем использовать receiveWithin в любом случае IMHO).
В приведенном ниже примере предписывается запустить runnable через 5 секунд:
import akka.actor.{ActorSystem, Scheduler}
import scala.concurrent.duration.FiniteDuration
import scala.concurrent.ExecutionContext.Implicits.global
class TimerExample {
def example() = {
def scheduler: Scheduler = ActorSystem.create("timer-example").scheduler
val myRunnable = new Runnable {
override def run(): Unit = {
println("run invoked")
}
}
println("scheduling...")
scheduler.scheduleOnce(FiniteDuration(5,TimeUnit.SECONDS),myRunnable)
Thread.sleep(6000)
println("should have printed 'run invoked'")
}