假设我有一个代码执行阻塞/长操作,返回未来,然后我需要对结果进行一系列转换 . 一个天真的例子是
longOperation().map(_ * 2).map(_.toString).map(_ + "bla").
每个映射都引入了一个上下文切换 . 有没有一种简单的方法来避免上下文切换?我知道trampoline执行上下文和Scalaz任务,但我正在寻找一些更简单的东西,可以应用于我知道的非常特定的地方,我不需要上下文切换 . (有点类似于收藏品的观点) .
一个更实际的例子是我有一个记录未来执行时间的函数 - 没有理由进行上下文切换只是为了记录时间(更不用说现在我正在测量执行时间所花费的时间'' onComplete'被遗嘱执行人逮捕
def timedFuture[T](metric: Histogram)(futureBlock: => Future[T])(implicit ec: ExecutionContext): Future[T] = {
val startTime = System.nanoTime()
val result: Future[T] = futureBlock
result onComplete (_ => metric.record((System.nanoTime - startTime) / 1000000))
result
}
4 回答
如果您想要作为单个事物执行严格/同步转换,请在Try实例上执行转换:
资料来源:https://viktorklang.com/blog/Futures-in-Scala-protips-5.html
使用不切换的ExecutionContext,如下所示:
从scala future document开始,还有一些参数暗示不使用这个参数,因为可以在意外的线程中调用runnable(回调) . 但是,如果您完全了解异步未来/承诺的工作原理,则可以使用它 .
实际上在cats-effect或play框架中有一些trampoline执行上下文 . 您可以将这些内容复制到项目中 .
注意,如果使用这样的执行上下文,请不要在flatMap / map主体内部执行阻塞调用
只要系统中有多个线程,就可以随时进行上下文切换,这取决于操作系统 . 虽然使用
.map
稍微增加了它对任何事情都很重要的可能性,因为切换的确切时刻是微不足道的(无论如何都在你的控制范围之外) . 所以,我不担心 .