2010-07-28 30 views
5

Tôi bắt đầu hai tác nhân từ xa trên một máy chủ mà chỉ phản hồi bất kỳ nội dung nào được gửi cho họ. Sau đó tôi tạo một diễn viên khác gửi một số tin nhắn (sử dụng !!) cho cả hai diễn viên và giữ một danh sách các đối tượng tương lai giữ các câu trả lời từ các diễn viên này. Sau đó, tôi lặp qua Danh sách này tìm nạp kết quả của mỗi Tương lai. Vấn đề là hầu hết thời gian một số tương lai không bao giờ trở lại, thậm chí nghĩ rằng các diễn viên tuyên bố nó đã gửi trả lời. Vấn đề xảy ra ngẫu nhiên, đôi khi nó sẽ được thông qua toàn bộ danh sách, nhưng phần lớn thời gian nó bị mắc kẹt tại một số điểm và treo vô thời hạn.chương trình bị treo khi sử dụng nhiều tương lai với nhiều diễn viên từ xa

Dưới đây là một số mã trong đó sản xuất các vấn đề trên máy tính của tôi:

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

Tôi đang làm gì sai?

+0

Tôi cũng đã thử sử dụng một cổng khác cho mỗi tác nhân nhưng có cùng kết quả. – Kevin

Trả lời

2

Tôi đoán vấn đề của bạn là do dòng này:

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

trong đó bạn lặp qua tất cả tương lai của bạn và ngăn chặn trên mỗi lần lượt, chờ đợi kết quả của nó. Chặn trên tương lai thường là một ý tưởng tồi và nên tránh. Thay vào đó, những gì bạn muốn làm là chỉ định một hành động để thực hiện khi kết quả của tương lai có sẵn. Hãy thử điều này:

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

Dưới đây là một cách khác để nói rằng với một sự hiểu biết cho:

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

This blog entry là một mồi tuyệt vời trên các vấn đề chặn trên tương lai và làm thế nào monadic tương lai vượt qua nó.

+0

Cảm ơn bạn đã trả lời, tôi nghĩ rằng tôi hiểu vấn đề tốt hơn bây giờ. Tuy nhiên, đoạn mã này bạn cung cấp cũng có hành vi kỳ lạ. Nó xử lý tương lai đầu tiên và sau đó chấm dứt chương trình mà không ném một ngoại lệ. Tôi cũng đã thử sử dụng Futures.awaitAll (10000, tương lai), nhưng thậm chí sau 10 giây vẫn còn thiếu kết quả. – Kevin

+0

Nó kết thúc vì bạn gọi exit() sau vòng lặp. Vòng lặp sẽ trở lại ngay lập tức với mã của tôi vì nó không còn chặn nữa, vì vậy bạn không muốn chỉ cần thoát khỏi đó nữa. –

+0

không, nó chấm dứt trước đó, tôi đã thêm báo cáo in và vòng lặp và rất nhiều công cụ gỡ lỗi khác. Tôi hiểu rằng vòng lặp này sẽ không chặn, nhưng không có gì sau khi dòng đó được xử lý. Bất kỳ ý tưởng nào tại sao Futures.awaitAll không hoạt động? Có vẻ như nó được viết riêng cho loại nhiệm vụ này. – Kevin

0

Tôi cũng đã thấy một trường hợp tương tự. Khi các mã bên trong thread ném một số loại ngoại lệ và thoát, tương lai.get không bao giờ trả về. Người ta có thể thử với một ngoại lệ của java.lang.Error vs java.lang.NoSuchMethodError. Tương lai tương ứng của sau sẽ không bao giờ trở lại.

Các vấn đề liên quan