使用for循环并行执行scala期货

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)

}

我想在下面的代码中并行执行函数 getrankgetDetails(一旦返回 getStudentRollNo)。我怎样才能做到这一点?

我试了下面的方法,好像还是顺序执行的

请告诉我如何并行执行

Future 在创建时开始计算。

for (a <- x; b <- y) yield ??? 被脱糖为 x.flatMap(a => y.map(b => ???)) flatMap()map() 在 Future 完成后执行它的参数。

getDetails() 可以在 getRank() 完成之前开始,方法是分开创建 FutureflatMap() 调用。

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

正如您可能猜到的那样,您当前的代码不会并行调用 getRank 和 getDetails,因为它在内部进行了理解。它是 map 操作的语法糖。要实现并行性,您需要在 for-comprehension 之外创建两个 futures。

val student = getStudentRollNo(name)
val detailsFuture = student map {s => getRank(rollNo) }
val rankFuture = student map {s => getDetails(rollNo) }

for {
  rank <- rankFuture
  details <- detailsFuture
} yield (rank + details)

您可以在理解中使用 zip 来并行地 运行 两个 Futures:

  def getStudentRecord(name: String) = {
    for {
      rollNo <- getStudentRoolNo(name)
      rankRollNo <- getRank(rollNo) zip getDetails(rollNo)
    } yield rankRollNo
  }

上面的getRankgetDetails同时是运行,结果是一个字符串元组。如果要生成单个字符串,则需要将 rankRollNo 分成单独的组件:

yield rankRollNo._1 + rankRollNo._2