差异 Await.ready 和 Await.result

Difference Await.ready and Await.result

我知道这是一个开放式的问题,我深表歉意。

我可以看到 Await.ready returns Awaitable.typeAwait.result returns T 但我还是把它们弄糊涂了。

两者有什么区别?

一个是阻塞的,另一个是非阻塞的吗?

一般来说,两者都是阻塞的。

不同之处在于 Await.ready 一直阻塞,直到 Future 在给定时间内完成(成功或失败)。

唯一的区别是 ready 会阻塞,直到 Awaitable 准备就绪,而 result 会产生结果类型 T

后记: 在实践中,如果你想执行一些操作,比如错误检查或日志记录,你会采取 Await.ready(...) 如果你想组合结果并在出现错误时抛出错误,请采取 Await.result(...).

根据经验 - 尽量避免等待。

它们都阻塞直到 future 完成,区别只是它们的 return 类型。

当您的 Future 抛出异常时,差异很有用:

def a = Future { Thread.sleep(2000); 100 }
def b = Future { Thread.sleep(2000); throw new NullPointerException }

Await.ready(a, Duration.Inf) // Future(Success(100))    
Await.ready(b, Duration.Inf) // Future(Failure(java.lang.NullPointerException))

Await.result(a, Duration.Inf) // 100
Await.result(b, Duration.Inf) // crash with java.lang.NullPointerException

两者最多阻塞给定 Duration。但是,Await.result 立即尝试 return 未来的结果,如果未来失败则抛出异常,而 Await.ready returns 是结果(SuccessFailure) 可以通过 value 属性 安全地提取。

后者在您还必须处理超时时非常方便:

val future = Future { Thread.sleep(Random.nextInt(2000)); 123 }

Try(Await.ready(future, 1.second)) match {
    case Success(f) => f.value.get match {
      case Success(res) => // handle future success 
      case Failure(e) => // handle future failure
    }
    case Failure(_) => // handle timeout
}

当使用Await.result时,超时异常和失败期货的异常是"mixed up"。

Try(Await.result(future, 1.second)) match {
    case Success(res) => // we can deal with the result directly
    case Failure(e) => // but we might have to figure out if a timeout happened
}