一个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() throws Exception {
System.out.println("MyWorker is starting");
}
@Override
public void postStop() throws Exception {
System.out.println("MyWorker is stopping");
}
@Override
public void onReceive(Object msg) throws Exception {
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因为意外停止工作,监视者就会收到一个通知。
public class WatchActor extends UntypedActor {
private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
public WatchActor(ActorRef ref) {
getContext().watch(ref);
}
@Override
public void onReceive(Object msg) throws Exception {
if(msg instanceof Terminated) {
System.out.println(String.format("%s has terminated, shutting down system",
((Terminated)msg).getActor().path()));
getContext().system().shutdown();
}
}
}
上述代码定义了一个监视者WatchActor,它本质上也是一个Actor,但不同的是,它会在它的上下文中watch一个Actor。如果将来找个被监视的Actor的退出终止,WatchActor就能收到一条Terminated消息。在这里,将打印终止消息Terminated中的相关Actor路径,并且关闭整个ActorSystem。
主函数如下:
public class DeadMain {
public static void main(String[] args) {
ActorSystem system = ActorSystem.create("deadwatch", ConfigFactory.load("samplehello.conf"));
ActorRef worker = system.actorOf(Props.create(MyWorker.class),"worker");
system.actorOf(Props.create(WatchActor.class,worker),"watcher");
worker.tell(MyWorker.Msg.WORKING, ActorRef.noSender());
worker.tell(MyWorker.Msg.DONE, ActorRef.noSender());
worker.tell(PoisonPill.getInstance(), ActorRef.noSender());
}
}
上述代码中,首先创建ActorSystem全局实例,接着创建MyWorker和WatchActor。第6行的Props.create()方法,它的第1个参数为要创建的Actor类型,第2个参数为这个Actor的构造函数的参数(在这里,就是要调用WatchActor的构造函数)。接着,向MyWorker先后发送WORKING和DONE两条消息。最后在第9行,发送一条特殊的消息PoisonPill。PoisonPill就是毒药丸,它会直接毒死接收方,让其终止。