Как я могу казнить актера Akka каждые 5 минут?

Я хотел бы знать, есть ли в Akka какой-либо механизм, который может периодически запускать актера?


person Evans Y.    schedule 15.03.2012    source источник
comment
Здесь я нашел идеальное решение: doc.akka.io/docs/ акка/2.0/скала/scheduler.html   -  person Evans Y.    schedule 15.03.2012


Ответы (4)


Вам действительно не нужен актор для этого в Akka 1.3.1, вы можете запланировать вызов функции каждые 5 минут следующим образом:

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

Однако, если вы хотите, чтобы это был актер по другим причинам, вы бы назвали его так:

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)

Если вы используете Akka 2.0, то это будет сделано так

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

Или отправляйте сообщение актеру каждые 5 минут, как это

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())
person kerryjj    schedule 25.03.2012
comment
Scheduler.schedule больше не существует - person Phil; 13.05.2016
comment
имейте в виду, что вам может понадобиться знать, что предыдущий вызов завершился до того, как новый сработает через 5 минут, по крайней мере, в некоторых случаях. Для этого вы можете использовать scheduleOnce с некоторой дополнительной логикой. - person matanster; 13.07.2016
comment
Если вы хотите сделать это из самого Актера, вы можете вызвать context.system.scheduler.schedule(<params>), чтобы выполнить свою работу по планированию. - person NateH06; 18.04.2018

Подход с использованием расписания является одним из хороших подходов, хотя сообщения могут ставиться в очередь, если работа, выполняемая по расписанию, настолько велика, что может занять больше времени, чем запланированный интервал. Если вы хотите, чтобы интервал возникал между концом одной итерации и началом следующей, используйте scheduleOnce со следующим шаблоном:

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 = ???
}
person mattinbits    schedule 27.07.2015
comment
Это актуальный ответ на 2016 год. Scheduler.schedule больше не является допустимым методом. - person Zee; 26.05.2016
comment
Не могли бы вы просто использовать context.system.scheduler.schedule(...) для отправки сообщений self каждые 5 минут? Это выглядело бы намного чище и избавило бы от необходимости переопределять preStart. - person Branislav Lazic; 05.06.2017
comment
@BranislavLazic Нет, весь смысл не устанавливать повторяющееся расписание состоит в том, чтобы избежать отправки другого сообщения действующему лицу, если когда-либо возникнет ситуация, в которой логике обработки требуется время сверх интервала между каждым запланированным сообщением. С помощью scheduleOnce() актор может занять столько времени, сколько ему нужно, чтобы выполнить любую необходимую работу, а затем, когда это безопасно, настроить другое расписание для отправки будущего сообщения самому себе. В некоторых ситуациях это позволяет избежать взаимоблокировок и других проблем с параллелизмом. - person speby; 19.07.2017

Более полный пример Java:

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() { ... }
}
person Brett Tofel    schedule 29.03.2018

Если кому-то нужен java-код, они могут сделать так

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