如何在Akka中使用setReceiveTimeout同步杀死子Actor

时间:2015-04-10 15:18:48

标签: multithreading akka

背景: 我正在使用C#,但我认为这个问题也适用于Java和Scala。我有一个主要的演员传递所有"工作信息"。这些工作可以同时执行,只要他们不共享共享"并发ID"。为了解决这个问题,我为每个"并发ID"产生了一个儿童演员。然后,我使用setReceiveTimeout清理孩子们闲置时的情况。

我无法弄清楚如何在没有竞争条件的情况下做到这一点。以下是一些不起作用的方法: 1)从Dictionary中删除孩子,并告诉孩子终止。这不起作用,因为消息可能在超时被触发之间以及父进程开始处理消息之前被添加到子队列中,从而导致消息丢失。 2)从Dictionary中删除孩子,然后发送PoisonPill。这不起作用,因为孩子可能会继续处理新工作。如果更多的工作到达父级,父级将创建一个新的子级,并且具有相同并发ID的两种东西同时运行。 3)从字典中删除孩子,"问"有消息的孩子。如果消息返回

如果孩子的队列中有任何消息,父母是否可以询问孩子? (这不是竞争条件,因为给孩子的所有消息都来自父母)

父母可以检查孩子的队列是否为空,孩子是否处理过任何事情?

我应该添加新消息吗"问"孩子如果完成了吗? (这样做是安全的,因为我知道父母是唯一一个发送消息的人,但如果孩子正在处理消息,或者如果孩子正在处理消息,那么这可能会阻止它。调度员的游泳池。

我的问题类似于这个问题,但是我添加了"并发ID"的附加约束,而不是担心"僵尸演员"谁正在关闭,只要僵尸没有工作并且不会得到更多的工作: Get or create child Akka actor and ensure liveness

1 个答案:

答案 0 :(得分:1)

Akka确保演员邮箱是私有的。一个演员的邮箱不是另一个演员的业务。父母检查孩子的邮箱是否为空将是错误的。

为什么你认为问会阻止?

一种选择:不要杀死孩子。如果你有一套固定的并发ID,你会一遍又一遍地使用,只需让所有的actor都活着。演员不会消耗太多资源。

另一种选择:

When the parent wants to kill the child:
send a PoisonPill to the child and remove him from the Dictionary.

When the parent receives a "job message" with concurrencyID:
if (Dictionary.contains(concurrencyID) {
    send message to child
} else {
    if (parent has child with name concurrencyID) {
        delay message - for example with scheduler // child is terminating
    } else {
        create a child with name concurrencyID
        send message to child
    }
}