sharath chandra sharath chandra - 1 month ago 9
Scala Question

scala futures execution in parallel using for-loop

package p1
import scala.util.Failure
import scala.util.Success
import scala.concurrent.Await
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._

object modCheck extends App {

def getStudentRoolNo(name: String) = Future {
println("getStudentRoolNo")
name match {
case "name1" => 1
case "name2" => 2
case _ => throw new Exception("No doesnt exist")
}
}

def getRank(roolNo: Int) = Future {
println("getRank")
Thread.sleep(500)
roolNo match {
case 1 => "1"
case 2 => "2"
case _ => throw new Exception("No roolNo exist")
}
}

def getDetails(roolNo: Int) = Future {
println("getDetails")
roolNo match {
case 1 => "details 1"
case 2 => "Details 2"
case _ => throw new Exception("No details exist")
}
}

def getStudentRecord(name: String) = {
for {
rollNo <- getStudentRoolNo(name)
rank <- getRank(rollNo)
details <- getDetails(rollNo)
} yield (rank + details)

}

getStudentRecord("name1").onComplete {
case Success(ground) => println(s"got my Details $ground")
case Failure(ex) => println("Exception!" + ex)
}

Thread.sleep(2000)

}


I want to execute functions
getrank
and
getDetails
in parallel in below code(once the
getStudentRollNo
is returned). How can I achieve this?

I Tried below way, It seems it still executing in sequentially

Please let me know , How to execute in parallel

Answer

Future starts computation when it's created.

for (a <- x; b <- y) yield ??? is desugared to x.flatMap(a => y.map(b => ???)) flatMap() and map() execute it's argument after a Future is completed.

getDetails() can start before completion of getRank() by separating creation of Future and flatMap() invocation.

for {
    rollNo <- getStudentRoolNo(name)
    rankFuture = getRank(rollNo)
    detailsFuture = getDetails(rollNo)
    rank <- rankFuture
    details <- detailsFuture
  } yield (rank + details)