2014-07-22 18 views
7

我創建了一羣執行一些工作然後停止的actor。在其中一些演員中,我調用返回Future的第三方API。在接收方法內調用Future並在此之後停止actor

MyActor extends Actor 
{ 
.... 

def receive = { 

    case MsgA => { 
    ... 
    //this evaluates to a Future 
    val p : Future = someFutureAPICall() 
    //stop the actor 
    context stop self 
    } 

} 

} 

現在因爲Future無阻塞演員會之後即停止(?),即使Future尚未完成。這種情況下的預期行爲是什麼?

例如,如果我在Future上有onComplete,那麼即使演員已停止,是否仍會執行該操作?

MyActor extends Actor 
{ 
.... 

def receive = { 

    case MsgA => { 
    ... 
    //this evaluates to a Future 
    val p : Future = someFutureAPICall() 

    p.onComplete { 
     //will these expressions ever be evaluated ? 
     case Success(x) => log.info("Success") 
     case Failure(f) => log.info("Failure") 
    } 
    //stop the actor 
    context stop self 
    } 

} 

} 

回答

8

是返回Future(第三方API)的代碼將立即執行並返回未完成的Future。

執行這個未來的完整性與開始活着的演員無關。

如果你不再需要該演員,則不需要等待未來完成,並且可以像在第一個示例中那樣停止演員。

如果您需要在未來的結果中對該演員做某些事情,則可以在該未來安裝onComplete回調。一旦未來完成,它可以發送消息給演員停止。例如是這樣的:

val myActor = self // Don't close over unstable actor reference by using self directly 
p.onComplete { 
    case Success(x) => myActor ! x; myActor ! akka.actor.PoisonPill // sends result to be processed and then stops actor 
    case Failure(f) => myActor ! akka.actor.PoisonPill // stops actor 
} 

EDIT

在意見提出的另一種替代方法是使用pipeTo使用模式。它做幾乎相同的事情。下面是它是如何在阿卡庫中實現:

def pipeTo(recipient: ActorRef)(implicit sender: ActorRef = Actor.noSender): Future[T] = { 
    future onComplete { 
    case Success(r) ⇒ recipient ! r 
    case Failure(f) ⇒ recipient ! Status.Failure(f) 
    } 
    future 
} 

這裏是你如何可以調用創建它的未來後:

p pipeTo myActor 

,你的演員將不得不關閉自己收到後的主要區別消息,並且通過Failure消息將該失敗清楚地傳達給演員。這種方法有點安全,因爲你必須通過一個ActorRef,你不必記得把它(自我)複製到一個變量中。

+2

您應該使用pipeTo模式代替: 'import akka.pattern.pipe p.pipeTo(self)' –

相關問題