下载示例文件
Hello World实例文件所运行的前置条件:Java8和Maven
- 下载实例文件可以通过示例官网Lightbend Tech Hubquot通过点击 CREATE A PROGECT FOR ME获取项目压缩文件。
- 解压缩文件通过IDEA导入即可。
运行实例
通过运行AkkaQuickstart.java中的Main方法,控制台即会输出如下结果:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building app 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- exec-maven-plugin:1.6.0:exec (default-cli) @ app ---
>>> Press ENTER to exit <<<
[INFO] [05/11/2017 14:07:20.790] [helloakka-akka.actor.default-dispatcher-2] [akka://helloakka/user/printerActor] Hello, Java
[INFO] [05/11/2017 14:07:20.791] [helloakka-akka.actor.default-dispatcher-2] [akka://helloakka/user/printerActor] Good day, Play
[INFO] [05/11/2017 14:07:20.791] [helloakka-akka.actor.default-dispatcher-2] [akka://helloakka/user/printerActor] Howdy, Akka
[INFO] [05/11/2017 14:07:20.791] [helloakka-akka.actor.default-dispatcher-2] [akka://helloakka/user/printerActor] Howdy, Lightbend
恭喜你,如果你看到以上结果说明您已经成功运行实例程序。下面我们将研究下实现这样一个简单示例的原理。
究竟发生了什么?
通过控制台我们可以看程序输出了几个简单的问候语,让我们看看究竟在程序运行时到底发生了什么?
首先,主程序创建了一个akka.actor.ActorSystem,它是Actors运行的容器。接下来它创建了3个Greeter Actor的实例和一个Printer Actor的实例。示例然后将消息发送给Greeter Actor实例,并将消息存储在Actor实例内部。最后,当Actor收到了指令消息则触发其将发送消息给Printer Actor,其可以将消息打印到控制台显示:
Akka通过Actors和异步消息模式具有许多优点。
定义Actors和messages
Messages可以是任何Object的子类,同时Messages也可以是原始类型的包装类所构成的数组或集合。
Hello World Actors采用了三种不同的消息:
- WhoToGreet:问候消息的接收者
- Greet: 执行问候操作的指令
- Greeting:包含问候信息的消息
当定义Actors和他们的消息时,最好遵循以下建议:
- 起一个好名字
- 由于Messages需要被不同线程分享,Messages应该是不可变的
- 一个良好的最佳实践是,将与Actor所关联的Messages以静态内部类的形式定义在Actor中,便于理解Actor所期望的与可处理的消息类型
- 并通过Actor中定义一个static props方法以此创建Actor,这也是一种比较通用的做法。
让我们通过Greeter 和 Printer Actor来举例最佳实践的形式:
The Greeter Actor
package com.lightbend.akka.sample;
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import com.lightbend.akka.sample.Printer.Greeting;
public class Greeter extends AbstractActor {
static public Props props(String message, ActorRef printerActor) {
return Props.create(Greeter.class, () -> new Greeter(message, printerActor));
}
static public class WhoToGreet {
public final String who;
public WhoToGreet(String who) {
this.who = who;
}
}
static public class Greet {
public Greet() {
}
}
private final String message;
private final ActorRef printerActor;
private String greeting = "";
public Greeter(String message, ActorRef printerActor) {
this.message = message;
this.printerActor = printerActor;
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(WhoToGreet.class, wtg -> {
this.greeting = message + ", " + wtg.who;
})
.match(Greet.class, x -> {
printerActor.tell(new Greeting(greeting), getSelf());
})
.build();
}
}
让我们来逐步讲解Greeter的功能:
- Greeter类继承了akka.actor.AbstractActor类,并实现了其createReceive方法。
- Greeter类构造器接收两个参数:
- String message:构建问候消息
- ActorRef printerActor:一个打印Actor的引用
- receiveBuilder 定义Actor的行为;
- static props 方法创建并返回了一个Props 实例;
The Printer Actor
Printer的实现也非常简单:
package com.lightbend.akka.sample;
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class Printer extends AbstractActor {
static public Props props() {
return Props.create(Printer.class, () -> new Printer());
}
static public class Greeting {
public final String message;
public Greeting(String message) {
this.message = message;
}
}
private LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
public Printer() {
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Greeting.class, greeting -> {
log.info(greeting.message);
})
.build();
}
}