【问题标题】:scala futures execution in parallel using for-loop使用for循环并行执行scala期货
【发布时间】:2016-10-07 04:19:11
【问题描述】:
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)

}

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

我尝试了下面的方式,它似乎仍然在顺序执行

请告诉我,如何并行执行

【问题讨论】:

    标签: scala for-loop concurrent.futures


    【解决方案1】:

    Future 在创建时开始计算。

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

    getDetails() 可以在 getRank() 完成之前通过分离创建 Future 和 flatMap() 调用来启动。

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

    【讨论】:

      【解决方案2】:

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

      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)
      

      【讨论】:

      • 感谢您的建议,我正在检查更多关于在 for 循环中编写代码(因为我的实际复杂逻辑很多,现在采用上述解决方案可能有点困难),我有修改了问题,为什么在这种情况下它也是按顺序执行的?
      • 然后可以移动 rankFuture = getRank(rollNo) 和后续行以产生部分。这将减少混乱并确保两个期货并行执行
      • for { rollNo
      【解决方案3】:

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

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

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

      yield rankRollNo._1 + rankRollNo._2
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-25
        • 1970-01-01
        • 2016-07-11
        • 1970-01-01
        • 1970-01-01
        • 2018-08-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多