Recently, I came across some odd behavior on a machine where the mapfunction returning Future[T]was executed sequentially. The same problem does not occur on other machines: the work alternates, as one would expect. Later, I discovered that this was probably because Scala was too smart and chose ExecutionContextwhich corresponded to the resources of the machine: one core, one working.
Here is some simple code that reproduces the problem:
import scala.concurrent._
import scala.concurrent.duration._
val ss = List("the", "quick", "brown", "fox",
"jumped", "over", "the", "lazy", "dog")
def r(s: String) : Future[String] = future {
for (i <- 1 to 10) yield {
println(String.format("r(%s) waiting %s more seconds...",
s, (10 - i).toString))
Thread.sleep(1000)
}
s.reverse
}
val f_revs = ss.map { r(_) }
println("Look ma, no blocking!")
val rev = f_revs.par.map { Await.result(_, Duration.Inf) }.mkString(" ")
println(rev)
Doing this on a machine with unusual behavior causes consistent output as follows:
Look ma, no blocking!
r(the) waiting 9 more seconds...
r(the) waiting 8 more seconds...
r(the) waiting 7 more seconds...
Custom provision ExecutionContext:
val pool = Executors.newFixedThreadPool(1)
implicit val ec = ExecutionContext.fromExecutor(pool)
. : , . -, FixedThreadPool s, , pool.shutdown() -.
, . , (, ), , ? ExecutionContext, , .