使用Scala futures时,具有相同执行上下文的链接回调是否会优化为同步调用?
Scala 2.10中的新未来为异步调用操作的每个操作使用执行上下文(包括使用Scala futures时,具有相同执行上下文的链接回调是否会优化为同步调用?,scala,future,scala-2.10,Scala,Future,Scala 2.10,Scala 2.10中的新未来为异步调用操作的每个操作使用执行上下文(包括map,filter等)。这是否意味着每个操作都将始终通过执行上下文单独调用,或者,当链接多个转换/过滤器时,是否可能优化此步骤(每个转换/过滤器使用相同的执行上下文) 也就是说,如果使用相同的执行上下文执行f.map(…).filter(…).map(…),此调用是执行一次execute()还是三次 如果scala future不进行上述优化,是否有一个更适合长链合成的替代框架可以进行上述优化?我无法提供任何指向文档的链
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.10Future
类型,因为它不一定表示正在运行的计算。相反,我们使用scalaz.Nondeterminsm
接口的函数显式地重新引入非确定性。这简化了我们的实现,使代码更容易推理,因为效果顺序和不确定性点是完全明确的,不依赖于Scala的求值顺序
重要提示:Future
不包括任何错误处理,通常只应作为构建块,供希望基于Future
的功能,但希望设计自己的错误处理策略的库作者使用。请参阅scalaz.concurrent.Task
,了解扩展Future
并进行适当错误处理的类型——它只是Future[other[Throwable,a]]
的包装器,带有许多额外的方便函数