2010-07-28 11 views
5

Rozpoczynam od dwóch zdalnych aktorów na jednym hoście, który po prostu odtwarza to, co do nich wysyłane. Następnie tworzę kolejnego aktora, który wysyła kilka komunikatów (używając !!) do obu aktorów i trzyma obiekty Listy obiektów przyszłości, w których znajdują się odpowiedzi od tych aktorów. Następnie przeglądam tę Listę, pobierając wynik każdej Przyszłości. Problem polega na tym, że przez większość czasu niektóre futures nigdy nie powracają, nawet jeśli aktor twierdzi, że wysłał odpowiedź. Problem pojawia się losowo, czasami przechodzi przez całą listę, ale przez większość czasu w pewnym momencie utknie i zawiesza się w nieskończoność.Program zawiesza się podczas używania wielu kontraktów futures z wieloma zdalnymi aktorami

Oto kod, który wywołuje ten problem na moim komputerze:

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() 
    } 
} 

Co robię źle?

+0

Próbowałem również użyć innego portu dla każdego aktora, ale otrzymałem taki sam wynik. – Kevin

Odpowiedz

2

Zgaduję problem wynika z tej linii:

futures.foreach(f => println(f())) 

w którym pętla przez wszystkie futures i blok na każdej z kolei, czekając na jej wynik. Blokowanie na kontraktach terminowych jest generalnie złym pomysłem i należy go unikać. Zamiast tego należy podać akcję, która ma wykonać , gdy dostępny jest wynik w przyszłości.. Spróbuj tego:

futures.foreach(f => f.foreach(r => println(r))) 

Oto alternatywny sposób powiedzieć, że z za zrozumienie:

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

This blog entry jest doskonałym podkładem na problem blokowania na futures i kontrakty monadycznego jak go pokonać.

+0

Dzięki za odpowiedź, myślę, że teraz lepiej rozumiem problem. Jednak ten fragment kodu, który podałeś, działa również dziwnie. Przetwarza pierwszą przyszłość, a następnie kończy program bez zgłaszania wyjątku. Próbowałem również używać Futures.awaitAll (10000, futures), ale nawet po 10 sekundach wciąż brakuje wyników. – Kevin

+0

Kończy się, ponieważ wywołuje się exit() po pętli. Pętla natychmiast wróci z moim kodem, ponieważ nie jest już blokowana, więc nie chcesz już po prostu tam wyjść. –

+0

nie, kończy się przed tym, dodałem instrukcje drukowania i pętle oraz wiele innych rzeczy do debugowania. Rozumiem, że ta pętla nie będzie blokować, ale nic po tej linii nie zostanie przetworzone. Każdy pomysł, dlaczego Futures.awaitAll nie działa? Wygląda na to, że został napisany specjalnie dla tego rodzaju zadań. – Kevin

0

Widziałem również podobny przypadek. Kiedy kod wewnątrz wątku zgłasza pewne typy wyjątków i kończy działanie, odpowiedni plik future.get nigdy nie wraca. Można spróbować podnieść wyjątek java.lang.Error kontra java.lang.NoSuchMethodError. Ta odpowiednia przyszłość nigdy nie powróci.

Powiązane problemy