Scala 当使用多个远程参与者的多个未来时,程序挂起

Scala 当使用多个远程参与者的多个未来时,程序挂起,scala,scala-2.8,actor,future,Scala,Scala 2.8,Actor,Future,我在一台主机上启动两个远程参与者,只需回显发送给他们的任何内容。然后我创建了另一个actor,它向两个actor发送一定数量的消息(使用!!),并保留一个包含这些actor回复的未来对象的列表。然后我循环这个列表,获取每个未来的结果。问题是,大多数时候,一些期货永远不会回来,即使演员声称已经发送了回复。这个问题是随机发生的,有时它会遍历整个列表,但大多数时候它会在某个点被卡住并无限期地挂起 以下是在我的机器上产生问题的一些代码: Sink.scala: import scala.actors.A

我在一台主机上启动两个远程参与者,只需回显发送给他们的任何内容。然后我创建了另一个actor,它向两个actor发送一定数量的消息(使用!!),并保留一个包含这些actor回复的未来对象的列表。然后我循环这个列表,获取每个未来的结果。问题是,大多数时候,一些期货永远不会回来,即使演员声称已经发送了回复。这个问题是随机发生的,有时它会遍历整个列表,但大多数时候它会在某个点被卡住并无限期地挂起

以下是在我的机器上产生问题的一些代码:

Sink.scala:

import scala.actors.Actor
import scala.actors.Actor._
import scala.actors.Exit
import scala.actors.remote.RemoteActor
import scala.actors.remote.RemoteActor._

object Sink {
  def main(args: Array[String]): Unit = {
     new RemoteSink("node03-0",43001).start()
     new RemoteSink("node03-1",43001).start()
   }
}
class RemoteSink(name: String, port: Int) extends Actor
{
 def act() {
    println(name+" starts")
    trapExit=true
    alive(port)
    register(Symbol(name),self)

    loop {
        react {
            case Exit(from,reason) =>{
                    exit()
            }
            case msg => reply{
                    println(name+" sending reply to: "+msg)
                    msg+" back at you from "+name
                }
        }
    }
 }
}
Source.scala:

import scala.actors.Actor
import scala.actors.Actor._
import scala.actors.remote.Node;
import scala.actors.remote.RemoteActor
import scala.actors.remote.RemoteActor._

object Source {
    def main(args: Array[String]):Unit = {
        val peer = Node("127.0.0.1", 43001)
        val source = new RemoteSource(peer)
        source.start()
    }
}
class RemoteSource(peer: Node) extends Actor
{
    def act() {
        trapExit=true
        alive(43001)
        register(Symbol("source"),self)

        val sinks = List(select(peer,Symbol("node03-0"))
                                   ,select(peer,Symbol("node03-1"))
                                )
        sinks.foreach(link)

        val futures = for(sink <- sinks; i <- 0 to 20) yield    sink !! "hello "+i
        futures.foreach( f => println(f()))

        exit()
    }
}
导入scala.actors.Actor
导入scala.actors.Actor_
导入scala.actors.remote.Node;
导入scala.actors.remote.RemoteActor
导入scala.actors.remote.RemoteActor_
对象源{
def main(参数:数组[字符串]):单位={
val对等=节点(“127.0.0.1”,43001)
val源=新的远程源(对等)
source.start()
}
}
类RemoteSource(对等:节点)扩展了Actor
{
def法案(){
trapExit=true
活着(43001)
寄存器(符号(“源”),自身)
val接收器=列表(选择(对等,符号(“节点03-0”))
,选择(对等,符号(“节点03-1”))
)
sinks.foreach(link)

val futures=for(sink我猜您的问题是由于这一行:

futures.foreach( f => println(f()))
在这种情况下,您循环遍历所有期货,并依次阻止每个期货,等待其结果。阻止期货通常是一个坏主意,应该避免。相反,您要做的是指定在期货结果可用时要执行的操作。请尝试以下操作:

futures.foreach(f => f.foreach(r => println(r)))
以下是另一种表达方式,以便于理解:

for (future <- futures; result <- future) { println(result) }

用于(future我也看到过类似的情况。当线程内的代码抛出某些类型的异常并退出时,相应的future.get永远不会返回。可以尝试引发java.lang.Error与java.lang.NoSuchMethodError的异常。后者对应的future永远不会返回。

我还尝试使用不同的每个参与者的端口,但得到相同的结果。感谢您的回复,我想我现在更好地理解了这个问题。但是,您提供的这段代码的行为也很奇怪。它处理第一个未来,然后在不引发异常的情况下终止程序。我还尝试使用Futures.awaitAll(10000,Futures),但即使在10秒后仍会丢失结果。它会终止,因为您调用了exit()在循环之后。循环将立即返回我的代码,因为它不再阻塞,所以你不想再简单地退出那里。不,它在此之前终止,我添加了打印语句和循环以及许多其他调试内容。我知道这个循环不会阻塞,但在那一行被处理之后不会阻塞。你知道吗hy Futures.awaitAll不起作用?它似乎是专门为这种任务编写的。