2013-10-15 39 views
1

我是很新的阿卡所以我的問題看起來很簡單:問一個演員,讓當他到達阿卡特定狀態迴應他2

我有一個演員叫workerA使用FSM,因此可無論是在這兩個州FinishedComputing

sealed trait State 
case object Finished extends State 
case object Computing extends State 

sealed trait Data 
case object Uninitialized extends Data 
case class Todo(target: ActorRef, queue: immutable.Seq[Any]) extends Data 

workerA接收GetResponse應該當且僅當它處於狀態Finished回答。

這樣做的正確方法是什麼?我知道我們應該避免在這個範式中受到阻礙,但這裏只是關注的頂級演員。 感謝

+0

看起來簡單或者我不明白的問題。當它未處於完成狀態 – Jatin

+0

時它應該執行什麼操作,而未處於完成狀態時,該actor將從各個其他actor中收集信息以創建要發送給GetResponse的發件人的結果。即使您認爲簡單的.thx – Mermoz

回答

1

我不一定相信你甚至需要FSM在這裏。當你有許多狀態和這些狀態之間的許多可能的(可能是複雜的)狀態轉換時,FSM是一個非常好的工具。就你而言,如果我理解正確,你基本上有兩種狀態;收集數據並完成。它似乎也只有一個單一的狀態轉換,從gathering -> finished。如果我有這一切都正確,那麼我會建議你只需使用become來解決你的問題。

我在下面有一些代碼來顯示我描述的一個簡單的例子。其基本思想是,主要演員將一些工作場所養殖給一些工人,然後等待結果。如果任何人在工作完成的時候要求結果,那麼演員將這個請求存儲起來直到工作完成。完成後,演員將回復任何詢問結果的人。代碼如下:

case object GetResults 
case class Results(ints:List[Int]) 
case object DoWork 

class MainActor extends Actor with Stash{ 
    import context._ 

    override def preStart = { 
    val a = actorOf(Props[WorkerA], "worker-a") 
    val b = actorOf(Props[WorkerB], "worker-b") 
    a ! DoWork 
    b ! DoWork 
    } 

    def receive = gathering(Nil, 2) 

    def gathering(ints:List[Int], count:Int):Receive = { 
    case GetResults => stash() 
    case Results(i) =>  
     val results = i ::: ints 
     val newCount = count - 1 
     if (newCount == 0){ 
     unstashAll() 
     become(finished(results))   
     child("worker-a") foreach (stop(_)) 
     child("worker-b") foreach (stop(_)) 
     } 
     else 
     become(gathering(results, newCount)) 
    } 

    def finished(results:List[Int]):Receive = { 
    case GetResults => sender ! results 
    } 
} 

class WorkerA extends Actor{ 
    def receive = { 
    case DoWork => 

     //Only sleeping to simulate work. Not a good idea in real code 
     Thread sleep 3000 
     val ints = for(i <- 2 until 100 by 2) yield i 
     sender ! Results(ints.toList) 
    } 
} 

class WorkerB extends Actor{ 
    def receive = { 
    case DoWork => 

     //Only sleeping to simulate work. Not a good idea in real code 
     Thread sleep 2000 
     val ints = for(i <- 1 until 100 by 2) yield i 
     sender ! Results(ints.toList)  
    } 
} 

然後,你可以如下測試:

val mainActor = system.actorOf(Props[MainActor]) 
val fut = mainActor ? GetResults 
fut onComplete (println(_)) 
+0

感謝'藏匿'是我一直在尋找 – Mermoz

0

您可以在FSM狀態模式匹配:

// insert pattern matching stuff instead of ... 

class MyActor extends Actor with FSM[State, Message] { 
    startWith(Finished, WaitMessage(null)) 

    when(Finished) { 
    case Event(Todo(... => 
     // work 
     goto(Computing) using Todo(...) 
    case Event(GetResponse(... => 
     // reply: sender ! msg // or similar 
    } 

    /* the rest is optional. You can use onTransition below to send yourself a message to report status of the job: */ 
    when(Busy) { 
    case Event(Finished(... => 
     // reply to someone: sender ! msg // or similar 
     goto(Finished) 
    } 

    onTransition { 
    case Finished -> Computing => 
     // I prefer to run stuff here in a future, and then send a message to myself to signal the end of the job: 
     self ! Finished(data) 
    } 

的編輯更具體地解決問題:

class MyActor extends Actor with FSM[State, Message] { 
    startWith(Finished, WaitMessage(null)) 

    when(Finished) { 
    case Event(Todo(... => 
     // work 
     goto(Computing) using Todo(...) 
    case Event(GetResponse(... => 
     // reply: sender ! msg // or similar 
     stay 
    } 

    initialize() 
} 
+0

是,請給出答案,但如果MyActor在忙時收到「GetResponse」,會發生什麼情況? – Mermoz

+0

@A我fgfgf?我沒有得到這一切... – Mermoz

+0

然後應該發生什麼取決於您的要求。在進入Finished狀態之前,您可以忽略GetResponse,或者可以使用Stash特徵來推遲處理GetResponse消息。無論如何,一個稍微更具體的問題會有所幫助(即:你想做什麼)。 –