如何使用 java 以函数式风格实现 akka actor
How implement akka actor in functional style with java
我在 java 中实现了简单的计数器 actor:
public class CounterJavaActor extends UntypedActor {
int count = 0;
@Override
public void onReceive(Object message) throws Exception {
if (message.equals("incr")) {
count += 1;
} else if (message.equals("get")) {
sender().tell(count, self());
}
}
}
在 coursera 的课程中 "Functional reactive programming in scala",我看到了计数器的功能实现:
/**
* Advantages:
* state change is explicit
* state is scoped to current behaviour
*/
class CounterScala extends Actor{
def counter(n: Int) : Receive = {
case "incr" => context.become(counter(n+1))
case "get" => sender ! n
}
def receive = counter(0)
}
更新:
我的问题是,在 java 中,我无法像在 scala counter(n+1)
中那样进行追索函数调用。含义:
public class CounterJava8Actor extends AbstractActor {
//counter(0) in scala
private PartialFunction<Object, BoxedUnit> counter;
private int n = 0;
public CounterJava8Actor() {
counter =
ReceiveBuilder.
matchEquals("get", s -> {
sender().tell(n, self());
}).
matchEquals("inc", s -> {
//become(counter(n+1) in scala
context().become(counter);
}).build();
receive(counter);
}
}
可以用 java 以函数式风格实现它吗?
根据文档,您可以在 java 8
中使用 become/unbecome
http://doc.akka.io/docs/akka/snapshot/java/lambda-actors.html#become-unbecome
这里是从那里复制的示例代码
public class HotSwapActor extends AbstractActor {
private PartialFunction<Object, BoxedUnit> angry;
private PartialFunction<Object, BoxedUnit> happy;
public HotSwapActor() {
angry =
ReceiveBuilder.
matchEquals("foo", s -> {
sender().tell("I am already angry?", self());
}).
matchEquals("bar", s -> {
context().become(happy);
}).build();
happy = ReceiveBuilder.
matchEquals("bar", s -> {
sender().tell("I am already happy :-)", self());
}).
matchEquals("foo", s -> {
context().become(angry);
}).build();
receive(ReceiveBuilder.
matchEquals("foo", s -> {
context().become(angry);
}).
matchEquals("bar", s -> {
context().become(happy);
}).build()
);
}
}
或者你可以使用 UntypedActor,就像这里的文档中解释的那样
http://doc.akka.io/docs/akka/snapshot/java/untyped-actors.html
public class Manager extends UntypedActor {
public static final String SHUTDOWN = "shutdown";
ActorRef worker = getContext().watch(getContext().actorOf(
Props.create(Cruncher.class), "worker"));
public void onReceive(Object message) {
if (message.equals("job")) {
worker.tell("crunch", getSelf());
} else if (message.equals(SHUTDOWN)) {
worker.tell(PoisonPill.getInstance(), getSelf());
getContext().become(shuttingDown);
}
}
Procedure<Object> shuttingDown = new Procedure<Object>() {
@Override
public void apply(Object message) {
if (message.equals("job")) {
getSender().tell("service unavailable, shutting down", getSelf());
} else if (message instanceof Terminated) {
getContext().stop(getSelf());
}
}
};
}
要了解如何向 Procedure
添加参数,您可以查看此答案:
Akka/Java getContext().become with parameter?
这里是 java 8
的实际解决方案
private PartialFunction<Object, BoxedUnit> counter(final int n) {
return ReceiveBuilder.
matchEquals("get", s -> {
sender().tell(n, self());
}).
matchEquals("inc", s -> {
context().become(counter(n + 1));
}).build();
}
public CounterJava8Actor() {
receive(counter(0));
}
我在 java 中实现了简单的计数器 actor:
public class CounterJavaActor extends UntypedActor {
int count = 0;
@Override
public void onReceive(Object message) throws Exception {
if (message.equals("incr")) {
count += 1;
} else if (message.equals("get")) {
sender().tell(count, self());
}
}
}
在 coursera 的课程中 "Functional reactive programming in scala",我看到了计数器的功能实现:
/**
* Advantages:
* state change is explicit
* state is scoped to current behaviour
*/
class CounterScala extends Actor{
def counter(n: Int) : Receive = {
case "incr" => context.become(counter(n+1))
case "get" => sender ! n
}
def receive = counter(0)
}
更新:
我的问题是,在 java 中,我无法像在 scala counter(n+1)
中那样进行追索函数调用。含义:
public class CounterJava8Actor extends AbstractActor {
//counter(0) in scala
private PartialFunction<Object, BoxedUnit> counter;
private int n = 0;
public CounterJava8Actor() {
counter =
ReceiveBuilder.
matchEquals("get", s -> {
sender().tell(n, self());
}).
matchEquals("inc", s -> {
//become(counter(n+1) in scala
context().become(counter);
}).build();
receive(counter);
}
}
可以用 java 以函数式风格实现它吗?
根据文档,您可以在 java 8
中使用 become/unbecomehttp://doc.akka.io/docs/akka/snapshot/java/lambda-actors.html#become-unbecome
这里是从那里复制的示例代码
public class HotSwapActor extends AbstractActor {
private PartialFunction<Object, BoxedUnit> angry;
private PartialFunction<Object, BoxedUnit> happy;
public HotSwapActor() {
angry =
ReceiveBuilder.
matchEquals("foo", s -> {
sender().tell("I am already angry?", self());
}).
matchEquals("bar", s -> {
context().become(happy);
}).build();
happy = ReceiveBuilder.
matchEquals("bar", s -> {
sender().tell("I am already happy :-)", self());
}).
matchEquals("foo", s -> {
context().become(angry);
}).build();
receive(ReceiveBuilder.
matchEquals("foo", s -> {
context().become(angry);
}).
matchEquals("bar", s -> {
context().become(happy);
}).build()
);
}
}
或者你可以使用 UntypedActor,就像这里的文档中解释的那样
http://doc.akka.io/docs/akka/snapshot/java/untyped-actors.html
public class Manager extends UntypedActor {
public static final String SHUTDOWN = "shutdown";
ActorRef worker = getContext().watch(getContext().actorOf(
Props.create(Cruncher.class), "worker"));
public void onReceive(Object message) {
if (message.equals("job")) {
worker.tell("crunch", getSelf());
} else if (message.equals(SHUTDOWN)) {
worker.tell(PoisonPill.getInstance(), getSelf());
getContext().become(shuttingDown);
}
}
Procedure<Object> shuttingDown = new Procedure<Object>() {
@Override
public void apply(Object message) {
if (message.equals("job")) {
getSender().tell("service unavailable, shutting down", getSelf());
} else if (message instanceof Terminated) {
getContext().stop(getSelf());
}
}
};
}
要了解如何向 Procedure
添加参数,您可以查看此答案:
Akka/Java getContext().become with parameter?
这里是 java 8
的实际解决方案private PartialFunction<Object, BoxedUnit> counter(final int n) {
return ReceiveBuilder.
matchEquals("get", s -> {
sender().tell(n, self());
}).
matchEquals("inc", s -> {
context().become(counter(n + 1));
}).build();
}
public CounterJava8Actor() {
receive(counter(0));
}