scala – 为了理解:如何按顺序运行Futures
鉴于以下方法……
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 …}有结果, 因此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} 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}") } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |