2016-04-29 76 views
-1

Akka(Java API)在這裏。假設我有兩個演員,WatchdogBlockingListener。他們都注射了相互之間的引用:獲取Akka演員等待外部輸入而不掛其他演員

// WARNING! 
// All code here is just Groovy-pseudocode 
class Watchdog extends UntypedActor { 
    ActorRef blockingListener 

    @Override 
    void onReceive(Object message) { 
     if(message in Init) { 
      blockingListener.tell(new StartListening(), self()) 
     } else if(message in SomethingHappened) { 
      ... 
     } 
    } 
} 

class BlockingListener extends UntypedActor { 
    ActorRef watchdog 

    @Override 
    void onReceive(Object message) { 
     if(message in StartListening) { 
      while(true) { 
       // Block and scan for input 
       String event = waitForNextEvent() 

       watchdog.tell(new SomethingHappened(event), self()) 
      } 
     } 
    } 
} 

我擔心的while(true)循環中BlockingListener將阻止兩個演員之間的正常通信。 會嗎?我擔心的是,當BlockingListener被告知要StartListening,它會:

  1. 輸入while(true)循環;然後
  2. 使BlockingListener線程掛起/等待,直到發生事件(在actor系統之外);然後
  3. 嘗試告訴Watchdog有關SomethingHappened(event)但是...
  4. Watchdog永遠不會收到SomethingHappened,因爲它仍然在等待自己的Init消息來完成正在處理

我對嗎?如果是這樣,這裏有什麼補救措施?我們如何讓BlockingListener監聽演員系統之外的事件並對它們做出響應?

+1

請勿使用演員來收聽活動。參與者的意圖是被動的,而不是投票/阻止。爲'waitForNextEvent'生成一個單獨的專用線程,並將該事件發送給actor。 –

+0

有趣,@SotiriosDelimanolis,謝謝+1!這裏只是好奇,那麼需要進行HTTP/REST調用或JDBC調用的actor呢? – smeeb

+1

對於HTTP,使用異步客戶端併成功回調,如果事件需要對響應執行某些操作,則將事件發回給actor。對於JDBC來說,這有點複雜,因爲沒有異步工具。您可以分派到專用線程池或演員池。 –

回答

1

ActorSystem包含一個默認調度程序,它本質上是一個線程池,您可以配置您自己的單獨調度程序,但是如果您沒有,將使用默認調度程序。

當有人向WatchDog也將被安排在調度員的一個線程運行的消息Init,它將把StartListening消息blockingListener,然後線程返回調度程序(如接收方法完成)。

BlockingListener然而,當有人發送它StartListening將被分配一個線程,它將永遠保持並永不返回調度程序。當它發送消息到watchdog它將取決於可用線程的數量,如果watchdog將永遠得到對該消息的反應。

一般來說Akka是圍繞不阻塞而設計的,所以你應該儘可能地避免這種情況,但是在某些情況下,它可能是不可避免的阻塞。

在這種情況下你應該做的是將這些參與者分離到一個單獨的調度器上(並且偏好基於線程池的調度器通過默認的叉式加入池),這將確保你的演員消耗一個線程不是問題爲您的系統的其他演員。

但是還有一個問題,即使你在自己的線程池中隔離了actor,那是因爲你的actor被困在while循環中(一個actor只能同時在一個線程中執行)它不會對發送停止消息做出反應,甚至不會關閉演員系統 - 演員系統將會掛起。

這可以通過定期打破循環,發送演員消息繼續,然後將最後添加到演員郵箱中,並允許它處理其他消息並可能停止。這需要waitForNextEvent方法有某種超時,以便它不會無限期地阻塞。