官方文档: http://developer.lightbend.com/guides/akka-quickstart-java/?_ga=2.177525157.1012573474.1504767665-546319647.1504766934
一. AKKA Hello World example :
1.首先需要创建一个ActorSystem, 它是所有Actor运行的容器.
2.其次创建Greeter Actor和Printer Actor.
3.发送消息到Greeter Actor实例, 它们会先在内部存储消息.
4.最后Greeter Actor里面的指令消息会触发它们发送消息给Printer Actor, 然后Printer Actor会执行对应的操作.
二. 定义Actors和messages
messages可以是任意类型(any subtype of Object).
当定义Actors和它们的messages时, 要遵守以下规范:
1.因为messages是Actor的公共API, 所以给messages定义名称的时候要富含语义以及特定领域的意义.
2.messages是不可变的, 因为它们在不同的线程之间共享.
3.把Actor相关的messages作为静态内部类放到Actor类中, 这样更容易理解actor需要处理什么类型的消息.
4.在Actor类中, 使用静态方法props描述如何构造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();
}
}
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();
}
}
三.创建Actor对象
Actor不能用过new来创建, 而是通过工厂来创建Actor对象, 工厂返回的不是actor实例, 而是一个引用akka.actor.ActorRef, 这个引用指向actor实例.
akka.actor.ActorSystem类似于Spring的BeanFactory. 它作为Actor的容器, 管理actor的生命周期. 工厂方法actorOf通过两个参数创建Actor对象, 一个参数是配置对象Props, 一个参数是actor的名称.
final ActorRef printerActor =
system.actorOf(Printer.props(), "printerActor");
final ActorRef howdyGreeter =
system.actorOf(Greeter.props("Howdy", printerActor), "howdyGreeter");
final ActorRef helloGreeter =
system.actorOf(Greeter.props("Hello", printerActor), "helloGreeter");
final ActorRef goodDayGreeter =
system.actorOf(Greeter.props("Good day", printerActor), "goodDayGreeter");
四. 异步通信
Actor是响应式的和消息驱动的. 一个Actor不会做任何事情知道它接收到一个消息.Actors通过异步消息来通信. 这确保了消息的发送者(sender)不用停下来等待它们的消息被接受者(recipient)处理. 相反的, 发送者只要把消息放到接收者的邮筒(mailbox)里后就可以去干别的事了. 而这个邮筒本子上是一个有序的消息队列. 来自同一个Actor的多条消息是有序的, 而来自不同的Actor的消息是交错的.
当actor不处理消息的时候是处于一个暂停的状态, 此时它不消耗除内存以外的任何资源.
五. 发送消息到Actor
把消息放到Actor的邮筒(mailbox)里, 需要调用ActorRef的tell方法. 举个栗子:
把消息发送给Greeter Actor :
howdyGreeter.tell(new WhoToGreet("Akka"), ActorRef.noSender());
howdyGreeter.tell(new Greet(), ActorRef.noSender()); howdyGreeter.tell(new WhoToGreet("Lightbend"), ActorRef.noSender());
howdyGreeter.tell(new Greet(), ActorRef.noSender()); helloGreeter.tell(new WhoToGreet("Java"), ActorRef.noSender());
helloGreeter.tell(new Greet(), ActorRef.noSender()); goodDayGreeter.tell(new WhoToGreet("Play"), ActorRef.noSender());
goodDayGreeter.tell(new Greet(), ActorRef.noSender());
Greeter Actor给Printer Actor发送消息:
printerActor.tell(new Greeting(greeting), getSelf());