如何对Akka actor系统进行阻塞/同步调用?

时间:2016-02-15 20:58:17

标签: java akka actor

Akka 2.4.1 Java API 。我现在没有足够的带宽来学习Scala,所以我想这里的代码示例也使用Java API。

我有一个现有的ActorSystem,它充满了异步演员,而且效果很好。我现在需要在同步上下文中重用这个actor系统,如下所示:

// Groovy pseudo-code; NOT inside the actor system here!
ComputationRequest request = new ComputationRequest(1, 7, true)
MasterActor master = actorSystem.get(...)
ComputationResult result = actorSystem.tell(master, request)

在Akka的文档中没有任何地方我看到一个明确的例子,即将动画发送到演员系统(从外部),然后检索结果。我可以在这里使用Futures吗?在Akka(代码示例)中处理这种模式的标准方法是什么?

2 个答案:

答案 0 :(得分:11)

ask模式可以满足您的需求。它希望目标参与者通过tell将回复“返回”getSender()。你会得到一个Future的响应,可以使用它(阻止,如果必须的话)。

import akka.dispatch.*;
import scala.concurrent.ExecutionContext;
import scala.concurrent.Future;
import scala.concurrent.Await;
import scala.concurrent.Promise;
import akka.util.Timeout;


ComputationRequest request = new ComputationRequest(1, 7, true);
MasterActor master = actorSystem.get(...);

Timeout timeout = new Timeout(Duration.create(5, "seconds"));
Future<Object> future = Patterns.ask(master, request, timeout);
ComputationResult result = (ComputationResult) Await.result(future, timeout.duration());

答案 1 :(得分:0)

您可以将包含在演员中的回调注入akka系统,并将其用作&#34;发件人&#34;告诉力学。完整的例子:

import akka.actor.*;
import akka.dispatch.Await;
import akka.dispatch.Future;
import akka.pattern.Patterns;
import akka.util.Timeout;

import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

public class Main {

    public static void main(String[] args) throws Exception {

        // init your akka system
        final ActorSystem system = ActorSystem.create("Cambria");
        final ActorRef worker = system.actorOf(new Props(Worker.class), "worker");
        worker.tell(new Work(10));

        // make callback
        final Consumer<Object> callback = a -> System.out.println("from the other side: " + a);

        // wrap call back into sub-actor
        class TheSpy extends UntypedActor {
            @Override
            public void onReceive(final Object message) throws Exception {
                callback.accept(message);
            }
        }

        // inject callback into the system
        final ActorRef theSpy = system.actorOf(new Props(TheSpy::new), "spy");

        // find actor you want to hack
        final ActorSelection found = system.actorSelection("/user/worker");
        // send it a message and observe using callback)
        found.tell(new Work(20), theSpy);

        final Timeout timeout = new Timeout(5, TimeUnit.SECONDS);
        final Future<Object> future = Patterns.ask(worker, new Work(30), timeout);
        final Work result = (Work) Await.result(future, timeout.duration());
        System.out.println(result);

        system.shutdown();
        system.awaitTermination();
    }
}

public class Worker extends UntypedActor {
    public void onReceive(Object message) {
        if (message instanceof Work) {
            Work work = (Work) message;
            System.out.println("work = " + work);
            getSender().tell(new Work(work.getStart() + 1));
        } else {
            unhandled(message);
        }
    }
}

public class Work {
    private final int start;

    public Work(int start) {
        this.start = start;
    }

    public int getStart() {
        return start;
    }

    @Override
    public String toString() {
        return "Work{" +
                "start=" + start +
                '}';
    }
}
相关问题