何时使用Akka而何时不使用?

时间:2014-05-27 16:43:02

标签: java multithreading akka

我目前处于这样的情况:我实际上通过使用Actors使事情更复杂,然后我不这样做。我需要在不阻塞主线程的情况下执行大量的Http请求。由于这是并发性的,我想尝试不同的锁定,我决定和Akka一起去。现在我处于两种方法之间的怀疑。

接近一个(在需要时创建新的演员):

public class Main {
    public void start() {
        ActorSystem system = ActorSystem.create();

        // Create 5 Manager Actors (Currently the same Actor for all but this is different in actual practise)
        ActorRef managers = system.actorOf(new BroadcastPool(5).props(Props.create(Actor.class)));
        managers.tell(new Message(), ActorRef.noSender());
    }
}

public class Actor extends UntypedActor {

    @Override
    public void onReceive(Object message) throws Exception {
        if (message instanceof Message) {
            ActorRef ref = getContext().actorOf(new SmallestMailboxPool(10).props(Props.create(Actor.class)));

            // Repeat the below 10 times
            ref.tell(new Message2(), getSelf());
        } else if (message instanceof Message2) {
            // Execute long running Http Request
        }
    }
}

public final class Message {
    public Message() {
    }
}

public final class Message2 {
    public Message2() {
    }
}

接近两个(事先创造了很多演员并希望它足够了):

public class Main {
    public void start() {
        ActorSystem system = ActorSystem.create();

        ActorRef actors = system.actorOf(new SmallestMailboxPool(100).props(Props.create(Actor.class)));
        ActorRef managers = system.actorOf(new BroadcastPool(5).props(Props.create(() -> new Manager(actors))));

        managers.tell(new Message(), ActorRef.noSender());
    }
}

public class Manager extends UntypedActor {

    private ActorRef actors;

    public Manager(ActorRef actors) {
        this.actors = actors;
    }

    @Override
    public void onReceive(Object message) throws Exception {
        if (message instanceof Message) {
            // Repeat 10 times
            actors.tell(new Message2(), getSelf());
        }
    }
}

public class Actor extends UntypedActor {

    @Override
    public void onReceive(Object message) throws Exception {
        if (message instanceof Message2) {
            // Http request
        }
    }
}

public final class Message {
    public Message() {
    }
}

public final class Message2 {
    public Message2() {
    }
}

所以这两种方法都有不同的方面。一个确保它可以随时处理进入的新请求,那些永远不必等待的请求。但它留下了许多永远不会被使用的演员。手上的两个重用了Actors,但其缺点是它可能没有足够的空间,并且无法在未来处理这些消息并且必须对消息进行排队。

解决这个问题的最佳方法是什么?人们最常见的解决方法是什么?

如果你认为我可以做得更好(有或没有Akka),请告诉我!我对Akka很新,很想了解更多。

2 个答案:

答案 0 :(得分:1)

基于给定的信息,它看起来像基于任务的并发的典型示例 - 而不是基于actor的并发。想象一下,您有一个执行HTTP请求的方法。该方法获取给定的URL并返回一个对象,而不会在共享内存上引起任何数据竞争

private static Page loadPage(String url) {
    // ...
}

您可以使用 Executor 轻松地同时获取页面。有不同种类的执行者,例如你可以使用一个固定数量的线程。

public static void main(String... args) {
    ExecutorService executor = Executors.newFixedThreadPool(5);
    List<Future<Page>> futures = new ArrayList<>();
    // submit tasks
    for (String url : args) {
        futures.add(executor.submit(() -> loadPage(url)));
    }
    // access result of tasks (or wait until it is available)
    for (Future<Page> future : futures) {
        Page page = future.get();
        // ...
    }
    executor.shutdown();
}

无需进一步同步。 Executor 框架负责处理。

答案 1 :(得分:1)

我使用混合方法:事先创建相对较小的演员池,在需要时增加它,但保持池的大小有限(当连接太多时拒绝请求,以避免因外出而崩溃记忆)。