从scala actor中检索对象

时间:2012-08-08 14:54:55

标签: scala actor

我有一个可以分发的密集型任务,但其最终结果需要累积并传递给另一个方法。

具体来说,假设我正在对大量文本文件中的单个文件进行单词计数。

到目前为止,我所制定的版本看起来像这样:

import scala.actors.Actor
import scala.actors.Actor._
import scala.collection.mutable.{ArrayBuffer => mArray}

case object Stop

class Collector(val bin: mArray[(String, Int)], tcount: Int) extends Actor {
  def act() {
    loop {
      receive {
        case (fn: String, val: Int) => {
          // the following "bin" object is what I ultimately need to get back
          bin.append((fn, val))
        }
        case Stop => {
          tcount -= 1
          if(tcount == 0) exit()
        }}}}}

class Processor(col: Collector, flist: Seq[File]) extends Actor {
  def act() {
    for(fn <- flist) {
      val wcount = count words in fn // just a place holder for word counting code
      col ! (fn, wcount)
    }    
    col ! (id, Stop)
  }
}

我可以想到几个自制方法使主方法等待收集器完成然后处理“bin”对象。

但是上面检索“bin”并将其交回main或者你有什么的正确scala方法是什么?

2 个答案:

答案 0 :(得分:0)

对于一个actor,你不会“检索”任何东西,因为调用actor方法可能很危险。

相反,你让演员发出答案。您可以为GET对象添加案例,或者您可以让它在bin的处理程序中的某处发送Stop

答案 1 :(得分:0)

您可以使用方法!! ping一个actor以创建将来的结果。接收消息的参与者可以使用reply填写结果。


但是,您通过使用执行程序来节省大量管理工作,这对于并行化任务更好(您在这里没有真正的并发情况会特别有用)。

以下是基于Scala 2.10(即将发布,您现在可以使用2.10.0-M6),因为它包含改进的并发框架:

import java.io.File
import concurrent._
import java.util.concurrent.Executors

// count words in a file - probably not the best possible way to write this
def wc(f: File): Int = io.Source.fromFile(f).getLines.map(
   _.split(' ').filterNot(_ == "").size).sum

// utility method to get files within a directory (non-recursive!)
def filesInDir(dir: File): Seq[File] = dir.listFiles.toSeq.filter(_.isFile)

// process method which takes a list of files, spawns a word-count for each
// and collects the individual future results into a `Map` whose future is returned
def process(files: Seq[File])(implicit exec: ExecutionContext)
: Future[Seq[(File, Either[Throwable, Int])]] = {
  val futs = files.map { f =>
    // `future` submits the body for asynchronous processing. In order to
    // gracefully handle IO errors, a successful result is wrapped in `Right`,
    // and an exception in `Left`. The caller can decide how to handle errors.
    future {
      f -> (try {
        Right(wc(f))
      } catch {
        case e: Throwable => Left(e)
      })
    }
  }
  // collect all the individual results into one result object.
  // the new single `Future` is only complete after all of the individual futures
  // have completed.
  Future.sequence(futs)
}

示例:

// use as many threads as there are processor cores
val poolSize = sys.runtime.availableProcessors()

// create a new executor context to be used for spawning
implicit val exec = ExecutionContext.fromExecutor(
  Executors.newFixedThreadPool(poolSize))

// call the process
val map = process(filesInDir(new File("/my/directory")))

// execute some body when the future is completed
map.onSuccess { case m =>
  m foreach println
}