为什么不呢Scala的未来有一个不用彷徨/获取(maxDuration)方法,迫使我们采取Await.result()呢?

dev*_*ium 11 scala future

get方法与Future类(我希望它驻留在哪里)解耦并且强制编码器必须知道这个被称为外部双方法类的方法有什么特别的优势Await吗?

Yuv*_*kov 16

get方法与Future类分离是否有任何特殊优势

是的,让开发人员难以做错事.A Future表示将在未来完成的计算,并且可能在当前调用点处不可用.如果您需要阻止未来,为什么不同步执行它?什么是在线程池上安排它,浪费一个完美的线程池线程?

文件说:

阻挡未来之外

如前所述,出于性能和防止死锁的缘故,强烈建议不要阻止未来.期货的回调和组合者是使用其结果的首选方式.但是,在某些情况下可能需要阻止,并且Futures and Promises API支持阻止.

甚至是Await对象文档:

虽然偶尔有用,例如用于测试,但建议您尽可能避免使用等待回调和组合器(如onComplete)并用于理解.Await将阻止它运行的线程,并可能导致性能和死锁问题.

您可以看到语言设计者有意想要这种效果.


Vik*_*ang 16

在接受的答案上提供更多的历史1:

当我们在Scala生态系统中正式确定大量的Future实现时,我们希望确保2我们没有标准化已知会产生问题的方法.

A Future表示与时间分离的值(或不能产生所述值).

更具体地说,意味着Future[T]信息严格少,简单T如下所示:

//At the line of this comment, there is no `f`
val f: Future[T] = … //At the line of this comment, there is an `f` but not necessarily its value of type `T`.
Run Code Online (Sandbox Code Playgroud)

鉴于:

//At the line of this comment, there is no `t`
val t: T = … //At the line of this comment, there is a `T`
Run Code Online (Sandbox Code Playgroud)

我听你说,为什么这很重要.好吧,如果你想拥有从一个方法Future[T]T,你说:我收到这可能不可用的值,我将回到它之后.

这意味着该方法在值尚未可用时必须"传递时间",这通常需要阻止当前执行线程,并且因为执行线程是一种昂贵的资源,并且通常需要时间才能进入阻塞状态并再次回来3,这是应该避免的.

好像这还不够,很容易陷入Futures无法完成的死锁,因为他们不会让Thread执行,因为所有这些线程都试图获得 Future的价值.

此外,我们意识到,只要Future实现有一个«blocking get»操作,许多用户会调用它而不会意识到它会对他们的程序产生什么影响,直到它在生产中产生问题,因为它看起来很简单,但是它的成本无处可见,直到为时已晚.

因此,我们决定推广不需要阻塞的编程风格,例如回调4和转换5,以降低死锁风险和性能不佳.

我们认为,如果我们完全忽略阻止从Future获得结果的能力,最终结果将是每个人都会重新发明它,并且可能具有不同的质量.

我们还发现,如果我们能够等待具体的东西,我们就会获得以下好处:

  • 所有Awaitables 的API看起来都一样
  • 代码审查很容易/反对
  • 使用工具很容易禁止/允许
  • 我们可以blocking尝试执行规避操作来缓解死锁,在运行时禁止它,记录它,计时等等.

所以你有它!

干杯,√

1从此成为SIP-14"期货和承诺"的共同创造者和维护者.

2当涉及到API时,你可以做到这一点......

3线程唤醒延迟可以有效地将处理限制在1k-10kops/s之间.

4我们也越来越不再强调使用回调,而是推广使用转换组合器,请参阅我为Scala 2.12 Futures撰写的这个博客系列.

5map,flatMap,filter,recover,recoverWith,以及最近transformtransformWith