我正在尝试处理futures
。这两者之间是否存在重大差异?
//1
import scala.concurrent.Await
import scala.concurrent.Future
import scala.concurrent.duration._
def longRequestToServer(): String = {...}
val future = Future { longRequestToServer() }
val resultAsync = Await.result(future, 60.seconds)
和
//2
val resultSync = try {
longRequestToServer()
} catch {
case _: Exception => "???"
}
除第一种情况中60 seconds
的时间段外。
答案 0 :(得分:14)
阻止是邪恶的。
在将来阻塞然后等待结果会消耗两个线程而不是一个。
那是邪恶的两倍吗?
这是你想要避免的拦截电话。
(将来,你至少要把它包裹在blocking
中,使其成为邪恶的一半。确切的比例实际上是.666邪恶。)
编辑:需要考虑的其他因素是两个版本在关机时可能会有不同的行为。在第一种情况下,未来可以被拒绝。协调这些影响,尤其是多个自定义执行程序和回调,相对微妙且容易出错。 (这是人们更喜欢演员的未来。)
(早期,所有throwable的期货并不完全健壮,因此您可能无法在工作线程上看到错误,但AFAIK已修复。)
答案 1 :(得分:4)
所以这两者之间有两点不同。
第二个是一个标准的非异步调用,你等待返回方法并阻塞当前线程并在之后进行错误处理。
在我看来,第一个是朝着正确方向迈出的一步。你将来开始长期运行的任务并且不会在原始线程上阻塞,但是因为你使用Await.result,你实际上创建了第二个线程,然后使用比之前的更多资源阻止第一个线程结束,但是你也没有做任何错误处理。
您应该做的是使用回调:http://docs.scala-lang.org/overviews/core/futures.html
val future = Future { longRequestToServer() }
future onSuccess {
case result => doSomething(result)
}
future onFailure {
case t => println("An error has occured: " + t.getMessage)
}
因此具有不使用长背景计算阻塞线程并进行错误管理的优点。
当然有时候使用Await.result是明智的,但大多数时候你可以编写一个带回调的非阻塞变体。