[英]Concurrent map/foreach in scala
我有一个迭代值vals: Iterable[T]
和一个长期运行的函数,没有任何相关的副作用: f: (T => Unit)
。 现在,这以明显的方式应用于vals
:
vals.foreach(f)
我希望同时完成对f
的调用(在合理的限制内)。 Scala基础库中某处有明显的功能吗? 就像是:
Concurrent.foreach(8 /* Number of threads. */)(vals, f)
虽然f
运行时间相当长,但它足够短,我不希望为每个调用调用一个线程的开销,所以我正在寻找基于线程池的东西。
2009年的许多答案仍然使用旧的scala.actors.Futures._,它们不再是新的Scala。 虽然Akka是首选方式,但更易读的方法是使用并行( .par )集合:
vals.foreach { v => f(v) }
变
vals.par.foreach { v => f(v) }
或者,使用parMap可能看起来更简洁,但需要记住要记住导入通常的Scalaz *。 像往常一样,Scala中有不止一种方法可以做同样的事情!
Scalaz有parMap
。 您可以按如下方式使用它:
import scalaz.Scalaz._
import scalaz.concurrent.Strategy.Naive
这将为每个parMap
函数(包括Iterable
)配备parMap
方法,因此您可以这样做:
vals.parMap(f)
您还可以获得parFlatMap
, parZipWith
等。
我喜欢Futures
答案。 但是,虽然它将同时执行,但它也将异步返回,这可能不是你想要的。 正确的方法如下:
import scala.actors.Futures._
vals map { x => future { f(x) } } foreach { _() }
我在Scala 2.8中使用scala.actors.Futures时遇到了一些问题(当我检查时它出了问题)。 使用java libs直接为我工作,但是:
final object Parallel {
val cpus=java.lang.Runtime.getRuntime().availableProcessors
import java.util.{Timer,TimerTask}
def afterDelay(ms: Long)(op: =>Unit) = new Timer().schedule(new TimerTask {override def run = op},ms)
def repeat(n: Int,f: Int=>Unit) = {
import java.util.concurrent._
val e=Executors.newCachedThreadPool //newFixedThreadPool(cpus+1)
(0 until n).foreach(i=>e.execute(new Runnable {def run = f(i)}))
e.shutdown
e.awaitTermination(Math.MAX_LONG, TimeUnit.SECONDS)
}
}
我使用scala.actors.Futures
:
vals.foreach(t => scala.actors.Futures.future(f(t)))
最新版本的Functional Java具有一些您可以使用的高阶并发功能。
import fjs.F._
import fj.control.parallel.Strategy._
import fj.control.parallel.ParModule._
import java.util.concurrent.Executors._
val pool = newCachedThreadPool
val par = parModule(executorStrategy[Unit](pool))
然后...
par.parMap(vals, f)
记得shutdown
pool
。
您可以使用Scala标准库中的Parallel Collections 。 它们就像普通的收藏品一样,但它们的操作并行运行。 您只需要在调用某些集合操作之前进行par
调用。
import scala.collection._
val array = new Array[String](10000)
for (i <- (0 until 10000).par) array(i) = i.toString
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.