Scala - 如何使用Await.result

时间:2017-11-30 13:22:34

标签: scala concurrency

我有akka-http提供的Rest API。在某些情况下,我需要从外部数据库(Apache HBase)获取数据,如果数据库花费太长时间来传递数据,我希望查询失败。

一种天真的方法是将呼叫包裹在Future内,然后使用Await.result将其阻止,并持有所需的持续时间。

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

object AsyncTest1 extends App {

  val future = Future {
    getMyDataFromDB()
  }

  val myData = Await.result(future, 100.millis)
}

由于此实现需要两个线程,因此似乎效率低下。有一种有效的方法吗?

我有另一个用例,我希望并行发送多个查询,然后聚合结果,并具有相同的延迟限制。

val future1 = Future {
    getMyDataFromDB1()
  }

  val future2 = Future {
    getMyDataFromDB2()
  }

  val foldedFuture = Future.fold(
    Seq(future1, future2))(MyAggregatedData)(myAggregateFunction)
  )

  val myData = Await.result(foldedFuture, 100.millis)

同样的问题,实现这个的最有效方法是什么?

感谢您的帮助

1 个答案:

答案 0 :(得分:3)

一种解决方案是使用Akka的after函数,它可以让你传递一个持续时间,之后将会抛出一个异常或任何你想要的东西。

看看here。它演示了如何实现这一点。

编辑: 我想我会在这里发布代码,以防链接在将来被破坏:

import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import akka.actor.ActorSystem
import akka.pattern.after

val system = ActorSystem("theSystem")

lazy val f = future { Thread.sleep(2000); true }
lazy val t = after(duration = 1 second, using = system.scheduler)(Future.failed(new TimeoutException("Future timed out!")))

val fWithTimeout = Future firstCompletedOf Seq(f, t)

fWithTimeout.onComplete {
   case Success(x) => println(x)
   case Failure(error) => println(error)
}