返回介绍

7.4 Actor 的生命周期

发布于 2024-08-21 22:20:21 字数 3540 浏览 0 评论 0 收藏 0

Actor在系统中产生后,也存在着“生老病死”的活动周期。Akka框架提供了若干回调函数,让我们得以在Actor的活动周期内进行一些业务相关的行为。Actor的生命周期如图7.1所示。

图7.1 Actor的生命周期

一个Actor在actorOf()函数被调用后开始建立,Actor实例创建后,会回调preStart()方法。在这个方法里,我们可以进行一些资源的初始化工作。在Actor的工作过程中,可能会出现一些异常,这种情况下,Actor会需要重启。当Actor被重启时,会回调preRestart()方法(在老的实例上),接着系统会创建一个新的Actor对象实例(虽然是新的实例,但它们都表示同一个Actor)。当新的Actor实例创建后,会回调postRestart()方法,表示启动完成,同时新的实例将会代替旧的实例。停止一个Actor也有很多方式,你可以调用stop()方法或者给Actor发送一个PosionPill(毒药丸)。Actor停止时,postStop()方法会被调用,同时这个Actor的监视者会收到一个Terminated消息。

下面让我们建立一个带有生命周期回调函数的Actor:

public class MyWorker extends UntypedActor {
  private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
  public static enum Msg {
    WORKING, DONE,CLOSE;
  }
  @Override
  public void preStart(){
    System.out.println("MyWorker is starting");
  }
  @Override
  public void postStop(){
    System.out.println("MyWorker is stopping");
  }
  @Override
  public void onReceive(Object msg) {
    if (msg == Msg.WORKING) {
      System.out.println("I am working");
    }
    if (msg == Msg.DONE) {
      System.out.println("Stop working");
    }if (msg == Msg.CLOSE) {
      System.out.println("I will shutdown");
      getSender().tell(Msg.CLOSE, getSelf());
      getContext().stop(getSelf());
    } else
      unhandled(msg);
  }
}

上述代码定义了一个名为MyWorker的Actor。它重载了preStart()和postStop()两个方法。一般来说,我们可以使用preStart()来初始化一些资源,使用postStop()来进行资源的释放。这个Actor很简单,当它收到WORKING消息时,就打印“I am working”,收到DONE消息时,打印“Stop working”。

接着,我们为MyWorker指定一个监视者,监视者就如同一个劳动监工,一旦MyWorker因为意外停止工作,监视者就会收到一个通知。

01 public class WatchActor extends UntypedActor {
02   private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
03
04   public WatchActor(ActorRef ref) {
05     getContext().watch(ref);
06   }
07
08   @Override
09   public void onReceive(Object msg) {
10     if (msg instanceof Terminated) {
11       System.out.println(String.format("%s has terminated, shutting down system",
12           ((Terminated) msg).getActor().path()));
13       getContext().system().shutdown();
14     } else {
15       unhandled(msg);
16     }
17   }
18 }

上述代码定义了一个监视者WatchActor,它本质上也是一个Actor,但不同的是,它会在它的上下文中watch一个Actor(第5行)。如果将来这个被监视的Actor的退出终止,WatchActor就能收到一条Terminated消息(代码第10行)。在这里,我们将简单地打印终止消息Terminated中的相关Actor路径,并且关闭整个ActorSystem(第13行)。

主函数如下:

01 public class DeadMain {
02   public static void main(String[] args) {
03     ActorSystem system = ActorSystem
04         .create("deadwatch", ConfigFactory.load("samplehello.conf"));
05     ActorRef worker = system.actorOf(Props.create(MyWorker.class), "worker");
06     system.actorOf(Props.create(WatchActor.class, worker), "watcher");
07     worker.tell(MyWorker.Msg.WORKING, ActorRef.noSender());
08     worker.tell(MyWorker.Msg.DONE, ActorRef.noSender());
09     worker.tell(PoisonPill.getInstance(), ActorRef.noSender());
10   }
11 }

上述代码中,我们首先创建ActorSystem全局实例(第3~4行),接着创建MyWorker Actor和WatchActor。注意第6行的Props.create()方法,它的第1个参数为要创建的Actor类型,第2个参数为这个Actor的构造函数的参数(在这里,就是要调用WatchActor的构造函数)。接着,向MyWorker先后发送WORKING和DONE两条消息。最后在第9行,发送一条特殊的消息PoisonPill。PoisonPill就是毒药丸,它会直接毒死接收方,让其终止。

执行上述代码,系统输出如下:

MyWorker is starting
I am working
Stop working
MyWorker is stopping
akka://deadwatch/user/worker has terminated, shutting down system

从这个输出中可以看到,MyWorker生命周期中的两个回调函数以及消息处理函数都被正常调用。最后一行输出也显示WatchActor正常监视到MyWorker的终止。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文