我想知道 Akka 中是否有任何机制可以定期执行 actor?
我想知道 Akka 中是否有任何机制可以定期执行 actor?
在 Akka 1.3.1 中,你不需要一个 actor 就能实现这个功能,你可以通过以下方式调度一个函数,使其每隔 5 分钟被调用:
Scheduler.schedule(() => println("Do something"), 0L, 5L, TimeUnit.MINUTES)
然而,如果你想让它成为一个Actor,出于其他原因,你应该像这样调用它
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分钟向一个Actor发送一条消息:
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())
scheduleOnce
和一些额外的逻辑。 - matanstercontext.system.scheduler.schedule(<params>)
来进行调度工作。 - NateH06使用定时器方式是一个不错的方法,但如果在定时器触发后需要执行的工作量太大,会导致消息队列积压。如果您希望定时器在一次迭代结束和下一次迭代开始之间发生,请使用以下模式的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 = ???
}
context.system.scheduler.schedule(...)
每5分钟向 self
发送消息呢?这样看起来更简洁,也消除了覆盖 preStart
的需要。 - Branislav Lazic更完整的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() { ... }
}
Cancellable cancellable = system.scheduler().schedule(Duration.Zero(), Duration.create(5, TimeUnit.MINUTES), cronActor, "tick", system.dispatcher(), null);