首页 文章

避免scala期货中不必要的上下文切换

提问于
浏览
0

假设我有一个代码执行阻塞/长操作,返回未来,然后我需要对结果进行一系列转换 . 一个天真的例子是

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 回答

  • 1

    如果您想要作为单个事物执行严格/同步转换,请在Try实例上执行转换:

    longOperation().transform(_.map(_ * 2).map(_.toString).map(_ + "bla"))
    

    资料来源:https://viktorklang.com/blog/Futures-in-Scala-protips-5.html

  • 0

    使用不切换的ExecutionContext,如下所示:

    val currentThreadExecutionContext = ExecutionContext.fromExecutor(
      new Executor {
        def execute(runnable: Runnable) { runnable.run() }
    })
    

    scala future document开始,还有一些参数暗示不使用这个参数,因为可以在意外的线程中调用runnable(回调) . 但是,如果您完全了解异步未来/承诺的工作原理,则可以使用它 .

  • 0

    实际上在cats-effect或play框架中有一些trampoline执行上下文 . 您可以将这些内容复制到项目中 .

    注意,如果使用这样的执行上下文,请不要在flatMap / map主体内部执行阻塞调用

  • 0

    只要系统中有多个线程,就可以随时进行上下文切换,这取决于操作系统 . 虽然使用 .map 稍微增加了它对任何事情都很重要的可能性,因为切换的确切时刻是微不足道的(无论如何都在你的控制范围之外) . 所以,我不担心 .

相关问题