J'aimerais savoir s'il existe un mécanisme à Akka qui peut faire exécuter un acteur périodiquement ?
Réponses
Trop de publicités?Vous n'avez pas vraiment besoin d'un acteur pour faire cela dans Akka 1.3.1, vous pouvez programmer 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'appelleriez ainsi
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 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())
L'approche utilisant la planification est une bonne approche, même s'il est possible que les messages se mettent en file d'attente si le travail effectué dans les délais est si important qu'il peut prendre plus de temps que l'intervalle planifié. Si vous souhaitez que l'intervalle se produise entre la fin d'une itération et le début de la suivante, utilisez alors 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 = ???
}
Exemple Java plus complet :
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() { ... }
}