“上面我们启动了ActorSystem,但是什么都没有,现在我们在里面创建一个actor,并给它发送消息。”
[TOC]
在上一篇的例子里,我们启动ActorSystem后什么也没干,现在改造RootBehavior.create()的逻辑,在里面创建actor。
actor需要定义与创建:
如下所示:
public static class RootBehavior {
static Behavior<Void> create() {
return Behaviors.setup(context -> {
// 创建一个actor,并给它发送消息
ActorRef<String> hello = context.spawn(HelloWorldActor.create(), "HelloWorld");
hello.tell("hi");
return Behaviors.empty();
}
);
}
}
创建/实例化一个actor是下面这句:
ActorRef<String> hello = context.spawn(HelloWorldActor.create(), "HelloWorld");
其中:
context.spawn()
:需要2个参数,第一个是定义actor的类,第二个是这个actor的名称。
ActorRef<String> hello
:是这个actor的引用,只有通过这个引用,才可以和这个actor交互。可以理解为actor引用是指向这个actor的地址。(注:由于Actor不同于面向对象思想,因此actor不是某个对象,需要通过引用获取。这带来的一个好处是,即使actor发生了重启,通过这个ActorRef依旧可以调用这个actor)
下面主要看下actor类的定义,即HelloWorldActor
:
public class HelloWorldActor extends AbstractBehavior<String> {
//常规操作:私有化构造方法
private HelloWorldActor(ActorContext<String> context) {
super(context);
}
//常规操作:通过create()静态方法返回经过封装的Behavior
public static Behavior<String> create() {
// return Behaviors.setup(HelloWorldActor::new);
return Behaviors.setup(context -> new HelloWorldActor(context));
}
@Override
public Receive<String> createReceive() {
return newReceiveBuilder()
.onMessage(String.class, this::onMsg)
.build();
}
//收到消息后,会进入此方法,即在此方法中实现处理消息的逻辑
private Behavior<String> onMsg(String msg) {
log.info("****** hello world actor"+ " 收到消息:{} \t", msg);
return this;
}
}
这里面有几个需要关注的点:
create()
静态方法提供经过Behaviors.setup()
封装过的实例。(官方写法,可能是因为akka不希望在别的地方创建和使用actor类的对象)createReceive()
方法,在里面指定收到消息后需要调用的方法,即onMsg()
,并实现onMsg()
这样,我们就实现了actor的定义和创建,并能给这个actor发消息。