Scala 中的 Actor 会无法处理消息吗? (O'Reilly 的 Scala 编程中的示例)

发布于 2024-10-14 14:24:58 字数 722 浏览 4 评论 0原文

我对 Scala 完全陌生,并且一直在在线学习 Scala 编程 (O'Reilly);这样做时,我对 第 1 章,“并发体验”

具体来说,是运行 scala -cp 的输出。 Shapes-actor-script.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 的了解还不够,不知道这是否是正常的,因为 Actor 的工作方式,或者我的 Scala 安装(Arch Linux 上的 Scala 2.8.1)是否有问题。

Actor 是否会无法处理这样的消息(可能是因为示例的编写方式)?或者还有什么我可能会错过的事情吗?

I'm completely new to Scala, and I've been working my way through Programming Scala (O'Reilly) online; while doing so, I was surprised by the result of the shapes-actor-script.scala example in Chapter 1, "A Taste Of Concurrency".

Specifically, the output of running scala -cp . shapes-actor-script.scala should be:

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...

Yet about 10% of the time, I get no output at all, and even more rarely, I'll get only the first line as output. I don't know enough about Scala yet to know if this is normal due to the way Actors work, or if something might be wrong with my Scala installation (Scala 2.8.1 on Arch Linux).

Can Actors fail to process messages like this (perhaps because of the way the example is written)? Or is there something else going on that I might be missing here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

囚我心虐我身 2024-10-21 14:24:58

我相信 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) }

I believe the Scala REPL is using System.exit(...) when it is finished running the script. That will stop the process without waiting for any lingering threads.

That means that all messages will be sent to the actor, but the actor might not be able to handle them in time.

To demonstrate you might try to add Thread.sleep(1000) to each of the cases in the 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)

This will probably make the script fail every time (it does on my machine). If you then add Thread.sleep(5000) (giving 2 secs of slack) it should succeed every time.

The solution is to use a program that does not end in System.exit(...).

Update (seconds thoughts):

You can also set up the actor to notify on exit:

case "exit"   => Thread.sleep(1000);println("exiting..."); this.synchronized { this.notify }; exit

... and then the script can wait for the notification:

ShapeDrawingActor.synchronized { ShapeDrawingActor.wait(10000) }
舞袖。长 2024-10-21 14:24:58

很抱歉这么长时间才回复这个帖子(因为我在书中写了这个例子:^/)。我相信真正的问题是 STDOUT 在所有操作系统(和 shell?)环境中默认情况下不会刷新,并且行为似乎根据 Scala 的版本而有所不同。今天晚上,我使用2.7.7编译并运行了代码。 OS X (10.6.6) 上的 2.8.0 和 2.8.1、Java 1.6.0_24-b07-334-10M3326 和 bash。

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

Sorry for the long delay in replying to this thread (since I wrote this example in the book :^/). I believe the real problem is that STDOUT isn't flushed by default on all OS (and shell?) environments and the behavior appears to differ depending on the version of Scala. This evening, I compiled and ran the code using 2.7.7. 2.8.0, and 2.8.1 on OS X (10.6.6), Java 1.6.0_24-b07-334-10M3326, and bash.

For 2.7.7 and 2.8.1, all the output was printed before the process exited. For 2.8.0, only some output appeared! When I added "System.out.flush" to the end of the shapes-actor-script.scala, all output was printed for 2.8.0.

渔村楼浪 2024-10-21 14:24:58

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

然后就归结为演员应该如何查看邮箱。它可以将其作为队列进行遍历。但它也可以随机地穿过它,这提供了一些有趣的特性。

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

Actually, that seems reasonable enough. See, the actor is concurrent with the script, and none of the lines in the script wait for an answer. So it is perfectly possible for many messages to have been delivered to the actor before the actor decides to process any of them.

It then comes down to how should an actor go through its mailbox. It can go through it as a queue. But it could also go randomly through it, which provides some interesting properties.

My guess is that Scala 2.7.x, which was the version available when the book was written, used a queuing algorithm by default, while version 2.8.1 uses a random algorithm.

疾风者 2024-10-21 14:24:58

简单的解决方案,将其添加到 Shapes-actor-script.scala 的末尾:

Thread.sleep(1000)

它将给 actor 在 REPL 终止之前打印所有各种 Shape 消息的时间。

Simple solution, add this to the end of shapes-actor-script.scala:

Thread.sleep(1000)

It'll give the actor time to print all the various Shape messages before the REPL terminates.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文