比方说,我有一个执行阻塞/长时间操作的代码,该操作返回一个将来的值,然后我需要对结果进行一堆转换。一个简单的例子是
longOperation().map(_ * 2).map(_.toString).map(_ + "bla").
每张地图都引入了上下文切换。有避免上下文切换的简单方法吗?我知道蹦床执行上下文和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
}
答案 0 :(得分:1)
如果您要执行严格/同步转换,请改为在Try实例上执行转换:
longOperation().transform(_.map(_ * 2).map(_.toString).map(_ + "bla"))
来源:https://viktorklang.com/blog/Futures-in-Scala-protips-5.html
答案 1 :(得分:0)
使用一个不会切换的ExecutionContext,像这样:
val currentThreadExecutionContext = ExecutionContext.fromExecutor(
new Executor {
def execute(runnable: Runnable) { runnable.run() }
})
在scala future document中,还有一些参数建议不要使用该参数,因为可运行(回调)可能在意外线程中被调用。但是,如果您完全了解异步未来/承诺的工作原理,就可以使用它。
答案 2 :(得分:0)
实际上,cats-effect或play框架中有一些蹦床执行上下文。您可以将这些内容复制到您的项目中。
请注意,如果您使用这样的执行上下文,请不要在flatMap / map主体内部进行阻塞调用
答案 3 :(得分:0)
只要系统中有多个线程,就可以随时进行上下文切换,这取决于操作系统。虽然使用.map
会稍微增加它在该确切时刻发生的可能性,但这对任何事情都没有关系,因为切换的确切时刻无关紧要(而且不受控制)。所以,我不用担心。