Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
scala中的并发map/foreach_Scala_Concurrency_Functional Programming - Fatal编程技术网

scala中的并发map/foreach

scala中的并发map/foreach,scala,concurrency,functional-programming,Scala,Concurrency,Functional Programming,我有一个迭代vals:Iterable[T]和一个没有任何相关副作用的长时间运行的函数:f:(T=>Unit)。现在,这以明显的方式应用于VAL: vals.foreach(f) 我希望对f的调用能够同时进行(在合理的范围内)。Scala基本库中是否有明显的函数?比如: Concurrent.foreach(8 /* Number of threads. */)(vals, f) 虽然f运行的时间相当长,但它足够短,我不希望每次调用都需要调用线程的开销,因此我正在寻找基于线程池的东西。我在sca

我有一个迭代
vals:Iterable[T]
和一个没有任何相关副作用的长时间运行的函数:
f:(T=>Unit)
。现在,这以明显的方式应用于
VAL

vals.foreach(f)
我希望对
f
的调用能够同时进行(在合理的范围内)。Scala基本库中是否有明显的函数?比如:

Concurrent.foreach(8 /* Number of threads. */)(vals, f)

虽然
f
运行的时间相当长,但它足够短,我不希望每次调用都需要调用线程的开销,因此我正在寻找基于线程池的东西。

我在scala 2.8中使用scala.actors.Futures时遇到了一些问题(我检查时发现有问题)。使用java LIB直接对我有效,不过:

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)))

我喜欢未来的答案。然而,虽然它将并发执行,但它也将异步返回,这可能不是您想要的。正确的方法如下:

import scala.actors.Futures._

vals map { x => future { f(x) } } foreach { _() }
import scalaz.Scalaz._
import scalaz.concurrent.Strategy.Naive
具有
parMap
。您将按如下方式使用它:

import scala.actors.Futures._

vals map { x => future { f(x) } } foreach { _() }
import scalaz.Scalaz._
import scalaz.concurrent.Strategy.Naive
这将为每个函子(包括
Iterable
)配备
parMap
方法,因此您只需执行以下操作:

vals.parMap(f)
您还可以获得
parFlatMap
parZipWith
,等等。

的最新版本具有一些您可以使用的高阶并发功能

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)
请记住关闭

您可以使用Scala标准库中的。 它们与普通集合一样,但它们的操作是并行运行的。在调用某些集合操作之前,只需执行
par
调用

import scala.collection._

val array = new Array[String](10000)
for (i <- (0 until 10000).par) array(i) = i.toString
导入scala.collection_
val数组=新数组[字符串](10000)

对于(我2009年的许多答案仍然使用旧的scala.actors.Futures.\uz,它们不再在新的scala中。虽然Akka是首选方法,但更具可读性的方法是只使用并行(.par)集合:

vals.foreach{v=>f(v)}

变成

<代码> Val.P.Frace{{V=>F(V)} <代码> < /P>


或者,使用parMap可能会显得更简洁,但需要注意的是,您需要记住导入常用的Scalaz*。与往常一样,在Scala中有多种方法可以完成相同的事情!

请注意,
VAL
是一个严格的集合——如果它是惰性的(在Scala 2.7中,这包括
范围
类)我想我们可以通过在
map
和当前
foreach
之间注入另一个
foreach
调用来解决这个问题
那将是一个我们必须注入的映射,而不是另一个foreach?我也不清楚惰性集合的映射是否严格。最安全的方法可能是调用toArray。你是对的,
foreach
显然是一个错误的东西,因为它返回
Unit
。我的错!:-)惰性集合上的
map
函数几乎总是非严格的,因此我们可以调用
toList
(或
toArray
),或者我们可以投影然后强制:
(vals map{x=>future{f(x)}投影)。foreach{uuz()}
。我不知道这是否比简单的
toList
好,但它肯定是不同的。当你说它“异步返回”是什么意思?这是否意味着它是非阻塞的?(为什么这会成为一个问题?)