erip
erip

Reputation: 16935

Why aren't my Scala futures executing in parallel?

I'm trying to run a series of dumb Scala Futures in parallel. I have the following code, which I expect to take ~10 seconds:

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

But what I find is that the onComplete takes ~30 seconds, so my jobs are running sequentially.

How can I make them run in parallel? Why aren't they running in parallel now?

Upvotes: 3

Views: 5317

Answers (3)

Vyacheslav Kondratenko
Vyacheslav Kondratenko

Reputation: 101

You also could use 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)
})

Upvotes: 7

Nyavro
Nyavro

Reputation: 8866

You can run these futures in parallel declaring variables first:

val foo = scalaFoo
val bar = scalaBar
val baz = scalaBaz

And then doing for:

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

Upvotes: 3

sheunis
sheunis

Reputation: 1544

You need to create them before the for expression, otherwise they wont run in parallel. If you change the methods to vals, it should work.

Upvotes: 11

Related Questions