Как написать таймер актера в Scala? - PullRequest
12 голосов
/ 08 ноября 2011

Мне нужен актер, чтобы отправлять сообщения каждую минуту. Как мне лучше всего добиться этого поведения? Насколько я понимаю, я боюсь использовать java.lang.Thread.sleep(long millis) как нить, которой могут поделиться многие актеры в Scala.

Ответы [ 6 ]

17 голосов
/ 08 ноября 2011

Или, как упомянул @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
12 голосов
/ 08 ноября 2011

Создайте актера с receiveWithin в качестве таймера.

3 голосов
/ 08 ноября 2011

Вы можете использовать Akka FSM для моделирования актера, который остается forMax миллис в состоянии ожидания, а затем отправляет сообщение, например, переключаясь в другое состояние при использовании onTransition и оставаясь там на 0Миллис, чтобы вернуться в состояние ожидания.На странице Акка есть хороший пример.

2 голосов
/ 08 ноября 2011
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
1 голос
/ 12 июля 2016

Поскольку scala.actors теперь устарел и заменяется актерами akka (а так как в akka-актерах нет реакции или receiveWithin), здесь описывается, как это сделать с использованием акторов akka (на самом деле это менее «хак», чем использованиеreceiveWithin в любом случае IMHO).

В приведенном ниже примере запланирован запуск запуска через 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'")
}
1 голос
/ 14 августа 2013

Я закончил созданием выделенного экземпляра 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)
...