2014-10-27 32 views
2

我有一个演员来控制GUI。 为了保证即时响应(没有卡在屏幕上),我将一个PinnedDispatcher分配给这个actor。为什么akka演员和线程是如此不同

val system = ActorSystem("sys1") 
def createMonitor(clients:Seq[ActorRef],init_QPS:Int) = system.actorOf(Props(new MonitorGUI)).withDispatcher("my-pinned-dispatcher")) 

配置文件就像

my-pinned-dispatcher { 
    executor = "thread-pool-executor" 
    type = PinnedDispatcher 
} 

演员的程序是这样的

class MonitorGUI() extends Actor { 
    val rate = 1000 milliseconds 
    val scheduler = context.system.scheduler 
    def receive = { 

    case GUIRefresh => 
     GUI.refresh() 
    case StartMonitor => 
     scheduler.schedule(rate + (300 milliseconds), rate ,self, GUIRefresh) 
    } 
} 

调度应该调用 “刷新” 每一秒。 但是,当有许多其他演员执行大量计算(例如98%CPU)时,调度程序无法保证每秒都会“刷新”。例如,GUI卡住了5秒钟。 但是纯线程程序比男主角程序更为敏感,就像这样:

new Thread(new Runnable { 
    override def run(): Unit = { 
    while (true){ 
     GUI.refresh 
     Thread.sleep(1000) 
    } 
    } 
}).start() 

我不知道为什么线程和演员是如此不同。因为这个演员应该有自己的线程。应该没有区别。

回答

2

参与者不像线程那样可抢占;当一个actor开始处理消息时,它将继续处理直到它完成该消息,并且只有这样才可以运行另一个actor。这是为了高吞吐量而设计的一个决定(它消除了上下文切换),但是在编写代码时需要注意它。

要么确保没有单个消息的处理运行时间超过您希望的延迟时间(可能是将计算拆分为小单元并发送新消息以触发每个步骤),要么为您的单独的执行上下文/调度程序使用计算繁重的演员和对延迟敏感的演员。 (理想情况下,您可能希望确保两个上下文中的线程总数等于物理CPU内核数量,以避免上下文线程阻塞另一个线程)。