好吧,让我们从秒示例开始。 考虑下面的代码片段:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object Test2{
def main(args:Array[String]):Unit={
val f = Future{Thread.sleep(5000); "i'm done"}
val r = for{
_ <- f
} yield "completed"
println(r)
}
}
猜猜它会打印?它打印
Future(<not completed>)
Process finished with exit code 0
所以其实这里你是不是等待将来完成时,您只需映射第一未来的结果,并返回它作为其他未来的第一个完成后,将完成。正如你所看到的,该计划不会等到最终的未来完成并正好退出。 for
对期货的理解是用于映射和平滑映射它们的糖语法。
该Await.result
和Await.ready
真的等待未来完成(或超时通过)。但是它们是以阻塞的方式实现的,所以你使用这些方法的线程将被阻塞。这并不总是很糟糕,有时可能会有所帮助。例如。在小测试程序或REPL会话中,您最终将未来计算的结果输出到控制台,或者例如在无论如何需要等待结果并且在等待测试时无需执行测试的情况下。
另一种看到你导致这样的小程序的方法是使用scala.io.StdIn.readLine()
,这样主线程就会挂起而不会退出。考虑其中说明了这以下,也为您提供了一个更多附加的方式来等待将来完成:
object Test2{
def main(args:Array[String]):Unit={
val f = Future{Thread.sleep(5000); "i'm done"}
f foreach (println(_))
scala.io.StdIn.readLine()
}
}
运行它,你会看到该程序不会退出,打印的未来和退出的结果,那么只有在您按下ENTER键后。
foreach
应用于未来是添加onComplete
侦听器的快捷方式。非常方便的一个。
至于如果未来完成while
循环不断地检查 - 我认为这可能是等待,因为它会继续在主线程忙,浪费更多的空闲CPU电源不是依靠高效地实现Await.result
最糟糕的方式。阻碍其他事情也可能是高效率和低效率的。
为了理解所有这些有未来的东西,你需要清楚地认识到,未来的实际执行不会发生在你发起它的同一个线程中。在我们所有的例子中,我们只是在主线程中定义了未来,然后在导入的执行上下文中的一个线程中执行了它。
理想情况下,你应该避免等待(尽可能地推出)和连锁期货(如在'for'理解中那样)。 – Thilo
如果你想在while循环中轮询,它应该是'while(!isCompleted)'。但最好使用'Await.ready',这是为了这个确切的目的而制作的。 – Thilo
hwan下面有两个貌似好的答案,他们有什么好处? – halfer