Scala中的参与者能否无法处理消息?(O&"x27;Reilly&"x27;s编程Scala中的示例)

Scala中的参与者能否无法处理消息?(O&"x27;Reilly&"x27;s编程Scala中的示例),scala,actor,Scala,Actor,我对Scala完全陌生,我一直在通过在线编程Scala(O'Reilly);这样做时,我对中的shapes-actor-script.scala示例的结果感到惊讶 具体来说,运行scala-cp的输出。shapes actor脚本。scala应为: Circle.draw: Circle(Point(0.0,0.0),1.0) Rectangle.draw: Rectangle(Point(0.0,0.0),2.0,5.0) Triangle.draw: Triangle(Point(0.0,0

我对Scala完全陌生,我一直在通过在线编程Scala(O'Reilly);这样做时,我对中的
shapes-actor-script.scala
示例的结果感到惊讶

具体来说,运行
scala-cp的输出。shapes actor脚本。scala
应为:

Circle.draw: Circle(Point(0.0,0.0),1.0)
Rectangle.draw: Rectangle(Point(0.0,0.0),2.0,5.0)
Triangle.draw: Triangle(Point(0.0,0.0),Point(1.0,0.0),Point(0.0,1.0))
Error: Unknown message! 3.14159
exiting...
然而,大约有10%的时候,我根本没有得到任何输出,更罕见的是,我只得到第一行作为输出。我对Scala的了解还不够,还不知道这是否正常,是因为Actors的工作方式,还是我的Scala安装(Arch Linux上的Scala 2.8.1)有问题


参与者是否会无法处理这样的消息(可能是因为编写示例的方式)?或者我在这里可能遗漏了什么?

我相信Scala REPL在运行完脚本后正在使用System.exit(…)。这将停止进程,而不等待任何延迟线程

这意味着所有消息都将发送给参与者,但是参与者可能无法及时处理它们

为了演示,您可以尝试将Thread.sleep(1000)添加到shapes-actor.scala中的每个案例中:

case s: Shape => Thread.sleep(1000);s.draw()
case "exit"   => Thread.sleep(1000);println("exiting..."); exit
case x: Any   => Thread.sleep(1000);println("Error: Unknown message! " + x)
这可能会使脚本每次都失败(在我的机器上)。如果然后添加Thread.sleep(5000)(提供2秒的空闲时间),则每次都应该成功

解决方案是使用一个不以System.exit(…)结尾的程序

更新(秒):

您还可以将参与者设置为在退出时通知:

case "exit"   => Thread.sleep(1000);println("exiting..."); this.synchronized { this.notify }; exit
。。。然后脚本可以等待通知:

ShapeDrawingActor.synchronized { ShapeDrawingActor.wait(10000) }

事实上,这似乎很合理。看,演员与剧本是同步的,剧本中没有一行等待答案。因此,在参与者决定处理其中任何一条消息之前,许多消息完全有可能已经传递给参与者

然后,问题就归结到演员应该如何通过邮箱。它可以通过它作为一个队列。但它也可以随机通过,这提供了一些有趣的特性


我的猜测是,Scala 2.7.x(本书编写时可用的版本)默认使用排队算法,而2.8.1版使用随机算法。

简单解决方案,将此添加到shapes-actor-script.Scala的末尾:

Thread.sleep(1000)

在REPL终止之前,它将为参与者提供打印所有各种形状消息的时间。

对于回复此线程的长时间延迟表示抱歉(因为我在书中写了此示例:^/)。我认为真正的问题在于,默认情况下,并非所有操作系统(和shell?)环境都会刷新STDOUT,而且根据Scala的版本,其行为似乎有所不同。今晚,我使用2.7.7编译并运行了代码。OS X(10.6.6)、Java 1.6.0_24-b07-334-10M3326和bash上的2.8.0和2.8.1


对于2.7.7和2.8.1,所有输出都是在流程退出之前打印的。对于2.8.0,只出现了一些输出!当我在shapes-actor-script.scala的末尾添加“System.out.flush”时,所有输出都是针对2.8.0打印的

即使在2.8.1中,参与者邮箱也是一个队列(请检查源)。