2013-12-11 157 views
1

我有一個使用scala運行的akka​​ actor系統。現在我需要並行配置多個設備,因此我有一個Manager actor來管理所有這些配置任務。要實際配置它們,他將爲每個配置產生一個Worker角色,以便它們同時運行或並行運行。現在,Worker演員在配置期間並不需要接收來自管理員的消息,他只需要做他的事情,然後報告他已完成回到Manager演員的良好做法?

現在的問題是我經過的說明和ManagerWorker的構造函數的ActorRef或做我創建它,然後將其發送的消息像Do(action: => Unit),然後在完成後將回復sender?有沒有一個會議如何做到這一點或被認爲是一種良好的做法?

編輯:作爲弗拉基米爾Matveev讓我想起了參考Manager不是因爲它是通過層次結構context.parent已知的問題。這隻留下了如何將工作交給Worker的問題。

+1

如果'Manager'直接產生工作人員,則不需要將'Manager'引用傳遞給他們。工作人員可以使用'context.parent'來訪問'Manager'' ActorRef'。 –

+0

@VladimirMatveev哦是的,這是真的。但是他們應該做的工作呢?如果我將來使用'context.scheduler.schedule ...'生成'context.parent'仍然是'Manager'?我認爲這應該是因爲它是封閉的,但我不確定這一點。 – mgttlinger

+1

如果你在一個actor中使用'context'來產生子actor,他們將把這個actor作爲父母,而不管你在這個actor中使用'context'的位置。這非常合乎邏輯,因爲正如你所說的,'context'變量剛剛結束,但它仍然是相同的'context'。 –

回答

2

你說得對,工作應該通過信息傳遞給工人。因爲這是與演員溝通的最安全的方式。它還使您能夠在演員面前使用調度員將分配的工作拆分爲多個工作人員。

爲了把事情說清楚,這裏是一個簡單的例子:

import akka.actor.Actor 
import akka.actor.Props 

case class Start() 
case class Finished() 
case class Do(action:() => Unit) 

class Manager extends Actor { 

    override def preStart() = 
    self ! Start() 

    def receive = { 
    case Start() => 
     val workers = context.actorOf(
     Props[Worker].withRouter(RoundRobinRouter(nrOfInstances = 5))) 
     context.system.scheduler.schedule(5 seconds, 5 seconds, workers, Do(() => 1 * 1)) 

    case Finished() => 
     println("A worker finished work.") 
    } 
} 

class Worker extends Actor { 
    def receive = { 
    case Do(f) => 
     f() 
     sender ! Finished() 
    } 
} 

經理被啓動後,它會創建5名工人,並給他們的東西,每5秒工作。工作人員將執行工作並在完成後進行報告。您可以使用sender(始終向工作發佈者報告)或context.parent(始終向經理報告)報告完成的工作。