2012-03-15 1 views

Répondre

54

Vous avez vraiment pas besoin d'un acteur à faire dans Akka vous 1.3.1 pouvez programmer une fonction à appeler toutes les 5 minutes comme ceci:

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

Cependant, si vous ne voulez qu'il soit un acteur pour d'autres raisons que vous appelleriez comme ça

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 vous utilisez 2.0, il serait Akka alors fait comme ce

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

ou envoyer un message à un acteur toutes les 5 minutes comme celui-ci

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 ne semble pas exister plus – Phil

+0

garder à l'esprit que vous voudrez peut-être savoir que l'invocation précédente fini son cours avant que le nouveau ne se déclenche après 5 minutes, dans certains cas au moins. Vous pouvez utiliser 'scheduleOnce' avec une logique supplémentaire, pour cela. – matanster

19

L'approche par le calendrier est une bonne approche, bien qu'il y ait un potentiel pour les messages à faire la queue si le travail effectué dans les délais prévus est si grand cela pourrait prendre plus de temps que l'intervalle prévu. Si vous voulez que l'intervalle de se produire entre la fin d'une itération et commençant de la suivante, utilisez scheduleOnce avec le motif suivant:

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

Ceci est la réponse pertinente à partir de 2016. Scheduler.schedule n'est plus une méthode valide. – Zee

+0

Ne pourriez-vous pas utiliser 'context.system.scheduler.schedule (...)' pour envoyer des messages à 'self' toutes les 5 minutes? Cela semblerait beaucoup plus propre et éliminerait le besoin de surcharger 'preStart'. –

+0

@BranislavLazic Non, le fait de ne pas définir un programme récurrent consiste à éviter d'envoyer un autre message à l'acteur s'il y a une situation où la logique de traitement nécessite un temps au-delà de l'intervalle entre chaque message planifié. Avec scheduleOnce(), l'acteur peut prendre autant de temps qu'il le faut pour effectuer tout le travail nécessaire, puis, lorsqu'il est en sécurité, configurer un autre programme pour lui envoyer un message futur. Dans certaines situations, cela peut éviter les interblocages et autres problèmes de concurrence. – speby

0

Si quelqu'un veux code java alors ils peuvent faire comme ça

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