为什么不';我的Scala期货不会并行执行吗?

为什么不';我的Scala期货不会并行执行吗?,scala,parallel-processing,future,Scala,Parallel Processing,Future,我正在尝试并行运行一系列愚蠢的ScalaFutures。我有以下代码,预计需要约10秒: import scala.concurrent.Future import scala.util.{Success, Failure} import scala.concurrent.ExecutionContext.Implicits.global def scalaFoo = Future { Thread.sleep(10*1000) // sleep for 10 seconds List

我正在尝试并行运行一系列愚蠢的Scala
Future
s。我有以下代码,预计需要约10秒:

import scala.concurrent.Future
import scala.util.{Success, Failure}
import scala.concurrent.ExecutionContext.Implicits.global

def scalaFoo = Future {
  Thread.sleep(10*1000) // sleep for 10 seconds
  List(1,2,3)
}

def scalaBar = Future {
  Thread.sleep(10*1000)
  List(4,5,6)
}

def scalaBaz = Future {
  Thread.sleep(10*1000)
  List(7,8,9)
}

val flatRes: Future[List[Int]] = for {
  scalaFooRes <- scalaFoo 
  scalaBarRes <- scalaBar
  scalaBazRes <- scalaBaz
} yield (scalaFooRes ++ scalaBarRes ++ scalaBazRes)

flatRes onComplete {
  case Success(li) => println(li.foldLeft(0)(_ + _))
  case Failure(e) => println(e.getMessage)
}
导入scala.concurrent.Future
导入scala.util.{成功,失败}
导入scala.concurrent.ExecutionContext.Implicits.global
def scalaFoo=未来{
Thread.sleep(10*1000)//睡眠10秒
清单(1,2,3)
}
def scalaBar=未来{
线程睡眠(10*1000)
清单(4,5,6)
}
def scalaBaz=未来{
线程睡眠(10*1000)
名单(7,8,9)
}
val flatRes:Future[列表[Int]]=for{

scalaFooRes您需要在for表达式之前创建它们,否则它们不会并行运行。如果您将方法更改为VAL,它应该可以工作。

您可以先并行运行这些期货声明变量:

val foo = scalaFoo
val bar = scalaBar
val baz = scalaBaz
然后为:

for {
  scalaFooRes <- foo 
  scalaBarRes <- bar
  scalaBazRes <- baz
} ...
用于{

scalaFooRes您还可以使用Future.sequence:

def scalaFoo = Future {
  Thread.sleep(3*1000) // sleep for 10 seconds
  List(1,2,3)
}

def scalaBar = Future {
  Thread.sleep(3*1000)
  List(4,5,6)
}

def scalaBaz = Future {
  Thread.sleep(3*1000)
  List(7,8,9)
}
Future.sequence(List(scalaFoo, scalaBar, scalaBaz)).onComplete({
  case Success(li) => println(li.flatten.sum)
  case Failure(e) => println(e.getMessage)
})

但是为什么呢?我在每个
scala*
函数中都放了一个print语句,在您的示例中,
foo
bar
baz
被定义后直接放了一个print语句,并发现打印出了问题。为什么这里的执行会出问题呢?@erip与并发编程通常的情况一样,没有保证当期货并行执行时,围绕执行顺序执行。@sheunis对于
只是
flatMap
的语法糖,这意味着期货只会在之前的完成之后运行。事先创建它们并分配给变量可以避免这个问题。如果你打开糖,那么在nmat的响应中添加您将看到调用链必须等待前一个将来完成,然后才能继续前进:
func1.flatMap(l1=>func2.flatMap(l2=>func3.flatMap(l3=>future{l1++l2++l3}))
确实如此。必须创建(并启动)未来当使用“val”时,未来的计算会立即开始(或者至少会立即安排)。使用“def”(方法)另一个观察结果是:为什么要在yield中创建一个列表,而不是将其展平?也可以使用“++”附加列表。我认为这会更快。