[英]Getting Akka actor to wait for external inputs without hanging other actors
Akka( Java API )在這里。 假設我有兩個演員, Watchdog
和BlockingListener
。 它們都注入了彼此的引用:
// 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())
}
}
}
}
我擔心BlockingListener
中的while(true)
循環會阻止兩個參與者之間的正確通信。 會嗎? 我擔心當BlockingListener
被告知StartListening
,它會:
while(true)
循環; 然后BlockingListener
線程掛起/等待直到一個事件(在actor系統之外)發生; 然后Watchdog
SomethingHappened(event)
,但是......Watchdog
永遠不會收到“發生了SomethingHappened
因為它仍在等待自己的Init
消息完成處理我對嗎? 如果是這樣,這里的補救措施是什么? 我們如何讓BlockingListener
監聽 actor 系統之外的事件並響應它們?
ActorSystem
包含一個默認調度器,它本質上是一個線程池,您可以配置自己的單獨調度器,但如果沒有,則將使用默認調度器。
當有人向WatchDog
發送消息Init
,它將被安排在調度程序的線程之一上運行,它會將StartListening
消息發送到blockingListener
StartListening
,然后將線程返回給調度程序(當接收方法完成時)。
然而,當有人發送它時, BlockingListener
會為StartListening
分配一個線程,它將永遠保留並且永遠不會返回給調度程序。 當它向watchdog
發送消息時,如果watchdog
對該消息做出反應,它將取決於可用線程的數量。
一般來說,Akka 是圍繞不阻塞而設計的,因此您應該盡可能避免這種情況,但在某些情況下可能無法避免阻塞。
在這種情況下,您應該做的是將這些 actor 隔離到一個單獨的調度程序上(並且更喜歡基於線程池的調度程序而不是默認的 Fork Join Pool),這將確保您的 actor 使用一個線程不會對另一個線程造成問題您系統的參與者。
然而,還有一個問題,即使您將 actor 隔離在其自己的線程池中,而且由於您的 actor 被困在 while 循環中(一個 actor 只會同時在一個線程中執行),因此它不會對發送停止消息做出反應,甚至關閉演員系統 - 演員系統將掛起。
這可以通過周期性地跳出循環來解決,向actor發送一條消息以繼續,然后該消息將最后添加到actor郵箱中並允許它處理其他消息並可能停止。 這需要waitForNextEvent
方法有某種超時,以便它不會無限期地阻塞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.