I ran across a surprising (to me) behavior this week: a parallel collection inside of a Future can use the Future’s execution context instead of any TaskSupport you explicitly set. To illustrate:
import scala.concurrent.ExecutionContext.Implicits.global
object ForkJoinTester {
def main(args: Array[String]): Unit = {
testForkJoinInner("ForkJoin(2)", new ForkJoinTaskSupport(new ForkJoinPool(2)))
Await.ready(Future(
testForkJoinInner("ForkJoin(2) in Future", new ForkJoinTaskSupport(new ForkJoinPool(2)))
), Duration.Inf)
Await.ready(Future(
testForkJoinInner("ForkJoin(1) in Future", new ForkJoinTaskSupport(new ForkJoinPool(1)))
), Duration.Inf)
Await.ready(Future(
testForkJoinInner("ThreadPool(2) in Future", new ExecutionContextTaskSupport(
ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))
))
), Duration.Inf)
sys.exit(0)
}
def testForkJoinInner(name: String, ts: TaskSupport): Unit = {
@volatile var tids = Set.empty[Long]
val p = Range(0, 10000).par
p.tasksupport = ts
p.foreach(_ => {
tids += Thread.currentThread().getId
})
println(s"$name: ${tids.size} threads")
}
}
The output:
ForkJoin(2): 2 threads
ForkJoin(2) in Future: 8 threads
ForkJoin(1) in Future: 1 threads
ThreadPool(2) in Future: 2 threads
As you can see, the ForkJoin(2) tasksupport is ignored when inside a Future, and the global context is used instead.
Is this expected? It seems wrong to me. I’m using Scala 2.11.
Thanks!