使用Scala futures时,具有相同执行上下文的链接回调是否会优化为同步调用?

使用Scala futures时,具有相同执行上下文的链接回调是否会优化为同步调用?,scala,future,scala-2.10,Scala,Future,Scala 2.10,Scala 2.10中的新未来为异步调用操作的每个操作使用执行上下文(包括map,filter等)。这是否意味着每个操作都将始终通过执行上下文单独调用,或者,当链接多个转换/过滤器时,是否可能优化此步骤(每个转换/过滤器使用相同的执行上下文) 也就是说,如果使用相同的执行上下文执行f.map(…).filter(…).map(…),此调用是执行一次execute()还是三次 如果scala future不进行上述优化,是否有一个更适合长链合成的替代框架可以进行上述优化?我无法提供任何指向文档的链

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

也就是说,如果使用相同的执行上下文执行
f.map(…).filter(…).map(…)
,此调用是执行一次
execute()
还是三次


如果scala future不进行上述优化,是否有一个更适合长链合成的替代框架可以进行上述优化?

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

只需打开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) 
它将打印:

scala>未来{1}映射(u+1)过滤器(>0)映射(+2)
执行
执行
执行
执行
res0:scala.concurrent.Future[Int]=scala.concurrent.impl.Promise$DefaultPromise@7ef3de76

因此,对于您正在执行的每个操作都会调用execute(正如您可以在文档中查看的那样,map或filter等每个函数都将ExecutionContext作为隐式参数:)

如果您正在寻找一个替代框架,您应该检查scalaz Futures。我没有与他们的经验,但他们似乎是你正在寻找的。检查此线程:

与scala 2.10中的
Future
实现不同,
map
flatMap
不产生新任务,也不需要隐式的
ExecutionContext
。相反,
map
flatMap
仅添加到将由“当前”线程运行的当前(蹦床)继续,除非通过
Future.fork
Future.apply显式分叉。这意味着
Future
实现了比2.10实现更好的线程重用,并避免了不必要的线程池提交周期

Future
也不同于scala 2.10
Future
类型,因为它不一定表示正在运行的计算。相反,我们使用
scalaz.Nondeterminsm
接口的函数显式地重新引入非确定性。这简化了我们的实现,使代码更容易推理,因为效果顺序和不确定性点是完全明确的,不依赖于Scala的求值顺序

重要提示:
Future
不包括任何错误处理,通常只应作为构建块,供希望基于
Future
的功能,但希望设计自己的错误处理策略的库作者使用。请参阅
scalaz.concurrent.Task
,了解扩展
Future
并进行适当错误处理的类型——它只是
Future[other[Throwable,a]]
的包装器,带有许多额外的方便函数