Je voudrais savoir s'il existe un mécanisme dans Akka qui peut faire exécuter périodiquement un acteur?
Vous n'avez pas vraiment besoin d'un acteur pour le faire dans Akka 1.3.1, vous pouvez planifier une fonction à appeler toutes les 5 minutes comme ceci:
Scheduler.schedule(() => println("Do something"), 0L, 5L, TimeUnit.MINUTES)
Cependant, si vous voulez que ce soit un acteur pour d'autres raisons, vous l'appellerez comme ceci
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 Akka 2.0, cela se ferait comme ceci
val system = ActorSystem("MySystem")
system.scheduler.schedule(0 seconds, 5 minutes)(println("do something"))
Ou envoyez un message à un acteur toutes les 5 minutes comme ceci
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())
L'approche utilisant la planification est une bonne approche, bien que les messages puissent être mis en file d'attente si le travail effectué selon le calendrier est si important qu'il peut prendre plus de temps que l'intervalle planifié. Si vous voulez que l'intervalle se produise entre fin d'une itération et début de la suivante, utilisez scheduleOnce
avec le modèle 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 = ???
}
Plus complet Java exemple:
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import scala.concurrent.duration.FiniteDuration;
import Java.util.concurrent.TimeUnit;
public class AnActor extends AbstractActor {
private final FiniteDuration SCHEDULED_WORK_DELAY = new FiniteDuration(5, TimeUnit.MINUTES);
@Override
public void preStart() {
getSelf().tell("Do Scheduled Work", ActorRef.noSender());
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("Do Scheduled Work", work -> {
doScheduledWork();
context().system().scheduler().scheduleOnce(SCHEDULED_WORK_DELAY, getSelf(),
"Do Scheduled Work", context().dispatcher(), ActorRef.noSender());
})
.build();
}
private void doScheduledWork() { ... }
}
Si quelqu'un veut Java code alors ils peuvent faire comme ça
Cancellable cancellable = system.scheduler().schedule(Duration.Zero(), Duration.create(5, TimeUnit.MINUTES), cronActor, "tick", system.dispatcher(), null);