Простой актер Scala - PullRequest
       11

Простой актер Scala

8 голосов
/ 02 апреля 2010

Я уверен, что это очень простой вопрос, но мне стыдно сказать, что я не могу разобраться с этим:

У меня есть список значений в Scala. Я хотел бы использовать актеры для параллельных вызовов (внешних) вызовов с каждым значением.

Я хотел бы подождать, пока все значения не будут обработаны, а затем продолжить.

Нет изменяемых общих значений.

Может кто-нибудь посоветовать?

Спасибо

Ответы [ 2 ]

17 голосов
/ 02 апреля 2010

В Scala есть класс, использующий актеров, который создан специально для такого рода проблем: Futures. Эта проблема будет решена так:

// This assigns futures that will execute in parallel
// In the example, the computation is performed by the "process" function
val tasks = list map (value => scala.actors.Futures.future { process(value) })

// The result of a future may be extracted with the apply() method, which
// will block if the result is not ready.
// Since we do want to block until all results are ready, we can call apply()
// directly instead of using a method such as Futures.awaitAll()
val results = tasks map (future => future.apply())

Вот, пожалуйста. Только это.

9 голосов
/ 02 апреля 2010

Создайте рабочих и спросите их о будущем, используя !!; затем прочитайте результаты (которые будут рассчитаны и введены параллельно, когда они будут готовы; затем вы можете использовать их). Например:

object Example {
  import scala.actors._
  class Worker extends Actor {
    def act() { Actor.loop { react {
      case s: String => reply(s.length)
      case _ => exit()
    }}}
  }
  def main(args: Array[String]) {
    val arguments = args.toList
    val workers = arguments.map(_ => (new Worker).start)
    val futures = for ((w,a) <- workers zip arguments) yield w !! a
    val results = futures.map(f => f() match {
      case i: Int => i
      case _ => throw new Exception("Whoops--didn't expect to get that!")
    })
    println(results)
    workers.foreach(_ ! None)
  }
}

Это делает очень недорогие вычисления - вычисление длины строки - но вы можете поместить что-то дорогое, чтобы убедиться, что это действительно происходит параллельно (последнее, что нужно сделать в случае блока действия, это ответ). Обратите внимание, что мы также включили случай, когда работник отключился, и когда мы все закончим, мы скажем работникам отключиться. (В этом случае любая не-строка выключает работника.)

И мы можем попробовать это, чтобы убедиться, что оно работает:

scala> Example.main(Array("This","is","a","test"))
List(4, 2, 1, 4)
...