Я уверен, что это очень простой вопрос, но мне стыдно сказать, что я не могу разобраться с этим:
У меня есть список значений в Scala. Я хотел бы использовать актеры для параллельных вызовов (внешних) вызовов с каждым значением.
Я хотел бы подождать, пока все значения не будут обработаны, а затем продолжить.
Там нет общих значений, которые будут изменены.
Кто-нибудь может посоветовать?
Спасибо
В 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())
Вот и все. Только то.
Создавайте рабочих и спрашивайте их о фьючерсах, используя !!
; затем считайте результаты (которые будут рассчитаны и поступать параллельно по мере готовности; затем вы можете их использовать). Например:
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)
}
}
Это очень недорогое вычисление - вычисление длины строки - но вы можете поместить туда что-нибудь дорогое, чтобы убедиться, что это действительно происходит параллельно (последнее, что в случае блока act должен быть ответить с ответом). Обратите внимание, что мы также включаем случай, когда воркер должен выключиться, и когда мы все закончим, мы говорим воркеру выключиться. (В этом случае любая нестроковая команда завершает работу воркера.)
И мы можем попробовать это, чтобы убедиться, что это работает:
scala> Example.main(Array("This","is","a","test"))
List(4, 2, 1, 4)