Scala actors可以同时处理多个消息吗? [英] Can Scala actors process multiple messages simultaneously?

查看:109
本文介绍了Scala actors可以同时处理多个消息吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对我最近的一个问题的回复一个actor一次处理一个 消息。这是真的?我没有看到任何明确说明(在 中的编程),其中包含以下代码段(第593页)

The reply to a recent question of mine indicated that an actor processed its messages one at a time. Is this true? I see nothing that explicitly says that (in Programming in Scala), which contains the following snippet (pp. 593)


如果[ react 方法]找到可以处理的邮件,[it]会安排处理该邮件以供日后执行并抛出异常

If [the react method] finds a message that can be handled, [it] will schedule the handling of that message for later execution and throw an exception

(强调我自己)。两个相关(和相互排斥的)问题:

(Emphasis my own). Two related (and mutually exclusive) questions:


  1. 假设一个actor可以同时处理多个消息,我如何强制actor处理消息1 (如果这是我想做的)? (使用 receive ?)

  2. 假设一个actor一次处理一个消息,我最好如何实现一个actor, em>可以同时处理邮件
  3. $ / $>
  1. Assuming an actor could process multiple messages simulatenously, how can I force an actor to process messages 1 at a time (if this is what I wish to do)? (using receive?)
  2. Assuming an actor processes messages one at a time, how would I best implement an actor which in fact could process messages concurrently

编辑:做一点测试似乎承认我错误,演员确实是顺序的。所以这是问题2,我需要回答

推荐答案

Actor一次处理一个消息。处理多个消息的经典模式是使一个协调器actor面向消费者actor池。如果使用react,那么使用者池可能很大,但仍然只使用少量的JVM线程。这里有一个例子,我创建了一个由10个消费者和一个协调器组成的池,供他们使用。

Actors process one message at a time. The classic pattern to process multiple messages is to have one coordinator actor front for a pool of consumer actors. If you use react then the consumer pool can be large but will still only use a small number of JVM threads. Here's an example where I create a pool of 10 consumers and one coordinator to front for them.

import scala.actors.Actor
import scala.actors.Actor._

case class Request(sender : Actor, payload : String)
case class Ready(sender : Actor)
case class Result(result : String)
case object Stop

def consumer(n : Int) = actor {
  loop {
    react {
      case Ready(sender) => 
        sender ! Ready(self)
      case Request(sender, payload) =>
        println("request to consumer " + n + " with " + payload)
        // some silly computation so the process takes awhile
        val result = ((payload + payload + payload) map {case '0' => 'X'; case '1' => "-"; case c => c}).mkString
        sender ! Result(result)
        println("consumer " + n + " is done processing " + result )
      case Stop => exit
    }
  }
}

// a pool of 10 consumers
val consumers = for (n <- 0 to 10) yield consumer(n)

val coordinator = actor {
  loop {
     react {
        case msg @ Request(sender, payload) =>
           consumers foreach {_ ! Ready(self)}
           react {
              // send the request to the first available consumer
              case Ready(consumer) => consumer ! msg
           }
         case Stop => 
           consumers foreach {_ ! Stop} 
           exit
     }
  }
}

// a little test loop - note that it's not doing anything with the results or telling the coordinator to stop
for (i <- 0 to 1000) coordinator ! Request(self, i.toString)

此代码测试查看哪个消费者可用并发送请求给消费者。替代方案只是随机分配给消费者或使用循环调度器。

This code tests to see which consumer is available and sends a request to that consumer. Alternatives are to just randomly assign to consumers or to use a round robin scheduler.

根据您所做的事情,您可能更适合使用Scala的期货。例如,如果你真的不需要actors,那么所有上面的机制可以写成

Depending on what you are doing, you might be better served with Scala's Futures. For instance, if you don't really need actors then all of the above machinery could be written as

import scala.actors.Futures._

def transform(payload : String) = {      
  val result = ((payload + payload + payload) map {case '0' => 'X'; case '1' => "-"; case c => c}).mkString
  println("transformed " + payload + " to " + result )
  result
}

val results = for (i <- 0 to 1000) yield future(transform(i.toString))

这篇关于Scala actors可以同时处理多个消息吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆