我对Akka很陌生,在参考手册中找不到答案。
假设我们有远程角色分布在3台机器(A,B,C)的集群中,其中一个角色存在于每台机器上,而其他角色则有actorRef到另外两台机器,即:
Machine A:
A (real actor)
-> B (ref)
-> C (ref)
Machine B:
-> A (ref)
B (real actor)
-> C (ref)
Machine C:
-> A (ref)
-> B (ref)
C (real actor)
Actor A执行以下代码:
bRef ! msg1
bRef ! msg2
Actor B在消息处理程序中执行以下代码:
case msg1 =>
cRef ! msg3
aRef ! msg4
Actor C在消息处理程序中执行以下代码:
case msg3 =>
aRef ! msg5
我可以做出以下假设(如果有的话):
演员B在获得msg2之前得到msg1
演员A获得msg5之前获得msg4
可能导致理解上述内容的后续问题: 是由!发送的消息!运营商是通过网络真正异步还是等到接收邮箱获得它? 即行
bRef ! msg1
阻止,直到演员B在其邮箱中获取消息或者它是否产生处理传递并继续执行的线程
bRef ! msg2
之前它甚至知道演员B得到了msg1?
答案 0 :(得分:8)
对于(1),您可以保证msg1将在msg2之前由调度员排队。一旦他们入队,实际发生的事情实际上取决于您使用的调度员:http://akka.io/docs/akka/1.1.2/scala/dispatchers.html,但在您的情况下,只要B可以接受这两个消息,那么它将始终在msg2之前接收msg1。
对于(2),不,你没有这个保证。的!一旦调度程序将消息排入队列,方法就会返回,而不是当目标actor的邮箱接受该消息时。然后发送在另一个线程中完成,并受到各种竞争条件的影响。
是否发送了消息!运营商是通过网络真正异步还是等到接收邮箱得到它?
您可以将BoundedMailbox与本地actor一起使用,以显示向调度程序排队的消息是异步的!:
class TestActor extends Actor {
val mailboxCapacity = BoundedMailbox(capacity = 1)
self.dispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher("test", 1, mailboxCapacity).build
def receive = {
case x: String =>
Thread.sleep(1000)
println("Received message")
case _ =>
}
}
val t = Actor.actorOf[TestActor]
t.start()
t ! "one"; t ! "two"; t ! "three"; println("Main thread");
打印:
scala> t ! "one"; t ! "two"; t ! "three"; println("Main thread");
Received message
Main thread
scala> Received message
Received message
这意味着在您甚至知道是否将传递消息之前,主线程中的代码执行仍在继续。在这种情况下,如果我们在调度程序上设置了pushTimeout并使Thread.sleep等待超过超时,则消息发送很容易超时。
将此与使用!!:
进行比较scala> t !! "one"; t !! "two"; t !! "three"; println("test");
Received message
Received message
Received message
test
所以,考虑到这一点。实现(2)的方法是:
case msg1 =>
cRef !! msg3
aRef ! msg4
答案 1 :(得分:1)
Erlang为您提供第一个保证,但不是第二个保证。 Akka可能会给你第一个保证,但肯定不会给你第二个保证。
我不知道你的后续问题的答案。