使用Scala期货时,将具有相同执行上下文的链接回调优化为同步调用吗?

Sof*_*mes 15 scala future scala-2.10

在斯卡拉2.10新的未来用来每一个地方的操作异步调用操作(包括执行上下文map,filter等等).这是否意味着每个操作将始终通过执行上下文单独调用,或者当使用相同的执行上下文链接多个转换/过滤器​​时,是否可能优化此步骤?

即如果这样做f.map(...).filter(...).map(...),所有具有相同的执行上下文,这将调用execute()一次(因为它足够聪明,从上面组成同步函数),或三次?

如果scala未来没有进行上述优化,是否有一个替代框架更适合长链组合,它确实做到了上述?

Pio*_*lka 10

我无法提供任何文档的链接,这些链接将清楚地说明将要发生的事情,但我们可以进行一个简单的实验来回答您的问题.

只需打开Scala REPL并粘贴以下代码:

import java.util.concurrent.Executors
import scala.concurrent._

implicit val ec = new ExecutionContext {
    val threadPool = Executors.newFixedThreadPool(1000);

    def execute(runnable: Runnable) {
        threadPool.submit(runnable)
        println("execute!")
    }

    def reportFailure(t: Throwable) {}
}

future { 1 } map(_ + 1) filter (_ > 0) map (_ + 2) 
Run Code Online (Sandbox Code Playgroud)

它将打印:

scala> future {1} map(_ + 1)filter(_> 0)map(_ + 2)
执行!
执行!
执行!
执行!
res0:scala.concurrent.Future [Int] = scala.concurrent.impl.Promise$DefaultPromise@7ef3de76

因此,对于您正在执行的每个操作都会调用execute(并且您可以在文档中检查每个函数,如map或filter,将ExecutionContext作为隐式参数:http://www.scala-lang.org/api/2.10.6 /#scala.concurrent.Future)

如果您正在寻找替代框架,您应该检查scalaz Futures.我没有他们的经验,但他们似乎是你在寻找.查看此主题:https://groups.google.com/forum/#! msg/scalaz/-PuakIf- g_4/7ydrU5VIfDQJ

Futurescala 2.10中的实现不同,map并且flatMap不生成新任务并且不需要隐式ExecutionContext.相反,mapflatMap只添加到将由"当前"线程中运行,除非通过明确分叉的电流(trampolined)延续Future.forkFuture.apply.这意味着Future实现了比2.10实现更好的线程重用,并避免了不必要的线程池提交周期.

Future也与scala 2.10 Future类型的不同之处在于它不一定代表运行计算.相反,我们使用接口的功能明确地重新引入非确定性scalaz.Nondeterminsm.这简化了我们的实现并使代码更易于推理,因为效果的顺序和非确定性的要点是完全明确的,并且不依赖于Scala的评估顺序.

重要说明:Future不包括任何错误处理,并且通常只应由想要构建Future其功能但希望设计自己的错误处理策略的库编写者用作构建块.请参阅scalaz.concurrent.Task针对Future通过适当的错误处理扩展的类型- 它仅仅是Future[Either[Throwable,A]]具有许多其他便利功能的包装器.