2012-03-30 24 views
2

我需要將一系列遠程調用切成塊。我想到了使用演員。如何讓scala參與者報告任務完成?

我認爲是這樣的:

class ControlActor() extends Actor{ 
    var counter = 1000 
    def act{ 
    for (i <- 1 until 1000) { new RequestActor(this) start } 
    while(true){ 
     receive{ 
     case "Stop" =>{counter = counter-1; if(counter==0){return}} 
     } 
    } 
    } 
} 

class RequestActor(parent:ControlActor) extends actor{ ... } 

但是這有一個明顯的問題:當我進入收到塊,一些RequestActor情況下,可能已經執行完畢。如果他們向尚未處於消息接收狀態的演員發送消息,會發生什麼情況?消息是排隊還是被丟棄?

最重要的是:如何創建小演員是能夠通知創建它們的演員,即使他們返回速度非常快?

此外相關:將當前actor實例(this)傳遞給其他參與者是否是一種好的做法?出於某種原因,我沒有看到有人這樣做。

+3

正如我告訴大家使用斯卡拉演員的問題,看看阿卡。它有非常高的真棒。 – leedm777 2012-03-30 03:26:12

回答

2

你是完美的罰款;演員中未處理的消息只會進入郵箱並在演員準備好時處理。然而,關於演員回答他們的來電,你一般不需要引用傳遞給this,因爲演員可以reply直接傳達給調用者。這裏有一個簡單的例子:

class MyActor(n: Int) extends Actor { 
    def act() { 
    loop { 
     react { 
     case m: Int => reply(n + m) // Use `reply` to reply to caller 
     } 
    } 
    } 
} 

// new MyActor(0), new MyActor(10), new MyActor(20), ... 
val actors = (0 to 100 by 10) map (new MyActor(_).start()) 

// Message each actor with '5', expecting a response (that's what `!?` does) 
val responses = actors map (_ !? 5) 
responses foreach println 

結果

5 
15 
25 
35 
45 
55 
65 
75 
85 
95 
105 

!?運營商,但是,將阻塞主線程,直到我們得到的回覆到它的消息。因此,actors map (_ !? 5)實際上不是所有的併發。相反,您可以使用!!生成期貨(您可以在此期間進行計算並推遲評估,直到您準備好爲止)。所以......最後兩行更改爲

val futures = actors map (_ !! 5) 
futures foreach (future => println(future())) 

將消息第一男主角與「5」,給我一個未來穩守在此期間,然後消息第二男主角與「5」,給我一個在此期間堅持下去的未來等等,當我們準備好時,我們可以評估未來(future())並以某種方式使用它的結果(如打印出來)。

1

只要一個演員已經開始,發送給它的消息將排隊等待下一個接收/呼叫作出反應。

通過構造函數傳遞的演員也很好,但你應該通過他們作爲演員,而不是派生類型,除去直接訪問演員的狀態的誘惑。

你通常不會看到這一點,因爲一般演員都沿消息傳遞。但是你在做什麼沒有錯。