加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 为了理解:如何按顺序运行Futures

发布时间:2020-12-16 09:56:53 所属栏目:安全 来源:网络整理
导读:鉴于以下方法…… def doSomething1: Future[Int] = { ... }def doSomething2: Future[Int] = { ... }def doSomething3: Future[Int] = { ... } ……以及以下的理解: for { x - doSomething1 y - doSomething2 z - doSomething3} yield x + y + z 这三种方
鉴于以下方法……

def doSomething1: Future[Int] = { ... }
def doSomething2: Future[Int] = { ... }
def doSomething3: Future[Int] = { ... }

……以及以下的理解:

for {
  x <- doSomething1
  y <- doSomething2
  z <- doSomething3
} yield x + y + z

这三种方法并行运行,但在我的情况下,doSomething2必须在doSomething1完成后运行.如何按顺序运行这三种方法?

编辑

如Philosophus42所示,以下是doSomething1的可能实现:

def doSomething1: Future[Int] = {
  // query the database for customers younger than 40;
  // `find` returns a `Future` containing the number of matches
  customerService.find(Json.obj("age" -> Json.obj("$lt" -> 40)))
}

…所以Future是通过对另一个方法的内部调用创建的.

编辑2

也许我过分简化了用例……我很抱歉.让我们再试一次,更接近真实的用例.以下是三种方法:

for {
  // get all the transactions generated by the exchange service
  transactions <- exchange.orderTransactions(orderId)

  //for each transaction create a log
  logs <- Future.sequence(tansactions.map { transaction =>
    for {
      // update trading order status
      _ <- orderService.findAndUpdate(transaction.orderId,"Executed")

      // create new log
      log <- logService.insert(Log(
        transactionId => transaction.id,orderId => transaction.orderId,...
      ))
    } yield log
  })
} yield logs

我要做的是为与订单关联的每个事务创建一个日志.即使事务只包含一个条目,也会多次调用logService.insert.

解决方法

评论你的帖子

首先,doSomethingX中的代码如何?更令人讨厌的是,使用您给定的代码,期货并行运行.

回答

为了使Future执行顺序,只需使用

for {
  v1 <- Future { ..block1... } 
  v2 <- Future { ..block2... } 
} yield combine(v1,v2)

这个工作的原因是,语句Future {..body ..}启动异步计算,在那个时间点评估语句.

随着上面的理解,desugared

Future { ..block1.. }
  .flatMap( v1 => 
     Future { ..block>.. }
       .map( v2 => combine(v1,v2) )
  )

很明显,那

>如果Future {… block1 …}有结果,
>触发flatMap方法,其中
>然后触发Future {… block2 …}的执行.

因此Future {… block2 …}在Future {… block1 …}之后执行

附加信息

未来

Future { 
  <block> 
}

通过ExecutionContext立即触发包含块的执行

小片1:

val f1 = Future { <body> }
val f2 = Future { <otherbody> }

这两个计算是并行运行的(如果你的ExecutionContext是这样设置的),因为这两个值是立即计算的.

摘录2:

构造

def f1 = Future { ..... }

一旦f1被调用,将开始执行未来

编辑:

j3d,我仍然感到困惑,为什么你的代码没有按预期工作,如果你的语句是正确的,那么Future是在computeSomethingX方法中创建的.

这是一个代码片段,证明,computeSomething2是在computeSomething1之后执行的

import scala.concurrent.{Await,Future}
????import scala.concurrent.duration._

object Playground {

  import scala.concurrent.ExecutionContext.Implicits.global

  def computeSomething1 : Future[Int] = {
    Future {
      for (i <- 1 to 10) {
        println("computeSomething1")
        Thread.sleep(500)
      }
      10
    }
  }

  def computeSomething2 : Future[String] = {
    Future {
      for(i <- 1 to 10) {
        println("computeSomething2")
        Thread.sleep(800)
      }
      "hello"
    }
  }

  def main(args: Array[String]) : Unit = {

    val resultFuture: Future[String] = for {
      v1 <- computeSomething1
      v2 <- computeSomething2
    } yield v2 + v1.toString

    // evil "wait" for result

    val result = Await.result(resultFuture,Duration.Inf)

    println( s"Result: ${result}")
  }
}

与输出

computeSomething1
computeSomething1
computeSomething1
computeSomething1
computeSomething1
computeSomething1
computeSomething1
computeSomething1
computeSomething1
computeSomething1
computeSomething2
computeSomething2
computeSomething2
computeSomething2
computeSomething2
computeSomething2
computeSomething2
computeSomething2
computeSomething2
computeSomething2
Result: hello10

编辑2

如果您希望它们并行执行,请事先创建期货(此处为f1和f2)

def main(args: Array[String]) : Unit = {
  val f1 = computeSomething1
  val f2 = computeSomething2

  val resultFuture: Future[String] = for {
    v1 <- f1
    v2 <- f2
  } yield v2 + v1.toString

  // evil "wait" for result

  val result = Await.result(resultFuture,Duration.Inf)

  println( s"Result: ${result}")
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读