2012-03-15 11 views

Respuesta

54

Usted realmente no necesita un actor para hacer esto en Akka 1.3.1 puede programar una función a ser llamada cada 5 minutos como esto:

Scheduler.schedule(() => println("Do something"), 0L, 5L, TimeUnit.MINUTES) 

Sin embargo, si usted quiere que sea un actor por otras razones que lo llamaría como esto

case class Message() 

val actor = actorOf(new Actor { 
    def receive = { 
    case Message() => println("Do something in actor") 
    } 
}).start() 

Scheduler.schedule(actor, Message(), 0L, 5L, TimeUnit.MINUTES) 

Si está utilizando Akka 2.0 a continuación, que sería hecho como éste

val system = ActorSystem("MySystem") 
system.scheduler.schedule(0 seconds, 5 minutes)(println("do something")) 

o enviar un mensaje a un actor cada 5 minutos como este

case class Message() 
class MyActor extends Actor { 
    def receive = { case Message() => println("Do something in actor") } 
} 

val system = ActorSystem("MySystem") 
val actor = system.actorOf(Props(new MyActor), name = "actor") 
system.scheduler.schedule(0 seconds, 5 minutes, actor, Message()) 
+3

Scheduler.schedule no parece existir mas – Phil

+0

tener en cuenta que es posible que desee saber que la invocación anterior terminó su curso antes de que el nuevo fuego después de 5 minutos, en algunos casos al menos. Puede usar 'scheduleOnce' con alguna lógica extra, para eso. – matanster

19

El método que utiliza horario es una buena aproximación, aunque hay una posibilidad de que los mensajes que hacer cola si el trabajo realizado en la fecha prevista es tan grande que podría tomar más tiempo que el intervalo programado. Si desea que el intervalo de que se produzca entre el final de una iteración y la comenzando de la siguiente, a continuación, utilizar scheduleOnce con el siguiente patrón:

import akka.actor.Actor 
import scala.concurrent.duration._ 

class SchedulingActor extends Actor { 

    override def preStart(): Unit = { 
    self ! "Do Some Work" 
    } 

    def receive = { 
    case "Do Some Work" => 
     doWork 
     context.system.scheduler.scheduleOnce(5 minutes, self, "Do Some Work") 
    } 

    def doWork = ??? 
} 
+2

Esta es la respuesta relevante a partir de 2016. Scheduler.schedule ya no es un método válido. – Zee

+0

¿No podría simplemente usar 'context.system.scheduler.schedule (...)' para enviar mensajes a 'self' cada 5 minutos? Se vería mucho más limpio y eliminaría la necesidad de anular 'preStart'. –

+0

@BranislavLazic No, el objetivo de no establecer un horario recurrente es evitar enviar otro mensaje al actor si alguna vez hay una situación en la que la lógica de procesamiento requiera tiempo más allá del intervalo entre cada mensaje programado. Con scheduleOnce(), el actor puede tomar todo el tiempo que necesite para completar cualquier trabajo que se necesite, y luego, cuando sea seguro, configure otro horario para enviarse un mensaje futuro. En algunas situaciones, esto puede evitar interbloqueos y otros problemas de concurrencia. – speby

0

Si alguien quiere el código de Java, entonces pueden hacer como esto

Cancellable cancellable = system.scheduler().schedule(Duration.Zero(), Duration.create(5, TimeUnit.MINUTES), cronActor, "tick", system.dispatcher(), null); 
Cuestiones relacionadas