我目前处于这样的情况:我实际上通过使用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很新,很想了解更多。
答案 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)
我使用混合方法:事先创建相对较小的演员池,在需要时增加它,但保持池的大小有限(当连接太多时拒绝请求,以避免因外出而崩溃记忆)。