Java 何时使用Akka,何时不使用?
我现在的处境是,当我不使用演员的时候,我实际上通过使用演员使事情变得更加复杂。我需要在不阻塞主线程的情况下执行大量Http请求。因为这是并发性,我想尝试一些不同于锁的东西,所以我决定使用Akka。现在我的处境是,我怀疑两种方法之间的区别 方法一:在需要时创建新的参与者:Java 何时使用Akka,何时不使用?,java,multithreading,akka,Java,Multithreading,Akka,我现在的处境是,当我不使用演员的时候,我实际上通过使用演员使事情变得更加复杂。我需要在不阻塞主线程的情况下执行大量Http请求。因为这是并发性,我想尝试一些不同于锁的东西,所以我决定使用Akka。现在我的处境是,我怀疑两种方法之间的区别 方法一:在需要时创建新的参与者: public class Main { public void start() { ActorSystem system = ActorSystem.create(); // Creat
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() {
}
}
所以这两种方法都有上下两面。我们要确保它总是能够处理新的请求,这些请求永远不必等待。但是它留下了很多永远不会被使用的演员。另一方面,两个应用程序重用了参与者,但缺点是它可能没有足够的参与者,并且无法应付将来的某个时间,并且必须对消息进行排队
解决这一问题的最佳方法是什么?人们处理这一问题的最常见方式是什么
如果你认为不管有没有Akka,我都可以做得更好,请告诉我!我对阿克卡很陌生,很想了解更多 根据给定的信息,它看起来像是基于任务的并发的典型示例,而不是基于角色的并发。假设您有一个执行HTTP请求的方法。该方法获取给定的URL并返回一个对象,而不会导致共享内存上的任何数据竞争:
private static Page loadPage(String url) {
// ...
}
您可以轻松地与执行器同时获取页面。有不同类型的执行器,例如,您可以使用具有固定线程数的执行器
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框架会解决这个问题。我会使用混合方法:事先创建相对较小的参与者池,在需要时增加参与者池,但在连接太多时保持池的大小限制拒绝请求,以避免因内存不足而崩溃。理想情况下提供实际代码。@djechlin,现在就可以了。为什么不使用?对于执行者来说,发出大量HTTP请求似乎是一个很好的例子,而对于参与者来说则不是。@djechlin我添加了一些代码。希望我这样做能让自己说得更清楚。@nosid那么你是说我应该放弃这种方法的整个参与者概念,而只使用执行者?所以基本上,在这方面,放弃参与者模型,使用普通的执行者服务?j.u.c.Future blocks来看看Java8 CompletableFuture或Scala的未来