使用Scala 2.11.8
,假设Future
在返回5
之前休眠()
秒,我调用akka.pattern.ask
时超时{{1}第二:
1
为什么import scala.concurrent.duration._
import scala.concurrent._
import akka.actor.ActorSystem
import scala.concurrent.ExecutionContext.Implicits.global
import akka.pattern.after
val system = ActorSystem.create()
after( FiniteDuration(1, SECONDS), system.scheduler)( Future{ Thread.sleep( 5000 ); () } )
res15: scala.concurrent.Future[Unit] = List()
// roughly 5 seconds later, I see:
scala> res15
res22: scala.concurrent.Future[Unit] = Success(())
没有res15
返回Failure
,因为Future
在5秒内没有完成,但是超时为1秒?
答案 0 :(得分:3)
After
方法会在延迟一段时间后运行您的未来。 duration
不是超时,它是启动延迟。 After
方法在内部使用了actorSystem schedular的scheduleOnce
方法。
After
是一种非常有趣的方法,它只在特定的持续时间后开始评估/执行你的未来表达式(即value
)。
如果给定的持续时间非常小,那么它会立即开始执行value
。
由于value
是按名称参数调用,因此不会立即评估该值。只有在通过名称值显式调用时才会评估value
。
以下是akka lib的代码。
def after[T](duration: FiniteDuration, using: Scheduler)(value: ⇒ Future[T])(implicit ec: ExecutionContext): Future[T] =
if (duration.isFinite() && duration.length < 1) {
try value catch { case NonFatal(t) ⇒ Future.failed(t) }
} else {
val p = Promise[T]()
using.scheduleOnce(duration) { p completeWith { try value catch { case NonFatal(t) ⇒ Future.failed(t) } } }
p.future
}
基本上你的持续时间会触发以下代码
using.scheduleOnce(duration) { p completeWith { try value catch { case NonFatal(t) ⇒ Future.failed(t) } } }
上述代码将在延迟后开始执行未来(duration
是延迟。)。
重要观察:
请注意,value
是按名称参数调用的。当按名称调用时,将评估value,这意味着除非显式调用value,否则将来不会开始执行。 value
在try中被调用,因为value
可能是一个包含大量代码并最终返回未来的多行表达式。
Promise(参见代码)会让你以非阻塞的方式等待,直到将来完成执行。 promise.future
只有在未来完成时才会完成。