事情是這樣的,也許:
object PimpMyFuture {
implicit class PimpedFuture[T](val f: Future[T]) extends AnyVal {
def after(delay: FiniteDuration)(callback: => Unit): Future[T] = {
Future {
blocking { Await.ready(f, delay) }
} recover { case _: TimeoutException => callback }
f
}
}
}
import PimpMyFuture._
Future { Thread.sleep(10000); println ("Done") }
.after(5.seconds) { println("Still going") }
這個實現很簡單,但它基本上雙打您需要的線程數 - 每個活躍的未來都有效地佔據兩條線索 - 這有點浪費。或者,您可以使用計劃任務使您的等待無阻塞。我不知道Scala中的一個「標準」調度(每個LIB都有自己的),但對於這樣一個簡單的任務,你可以使用Java的TimerTask
直接:
object PimpMyFutureNonBlocking {
val timer = new java.util.Timer
implicit class PimpedFuture[T](val f: Future[T]) extends AnyVal {
def after(delay: FiniteDuration)(callback: => Unit): Future[T] = {
val task = new java.util.TimerTask {
def run() { if(!f.isCompleted) callback }
}
timer.schedule(task, delay.toMillis)
f.onComplete { _ => task.cancel }
f
}
}
}
但是'firstCompletedOf'不會取消其他未來如果第一個返回。所以如果我的期貨的大部分時間是最後幾毫秒,但我想在30秒後添加一條調試語句,我將創建大量的Thread.sleep(30000),它不會被正確取消? – pathikrit
@pathikrit是的,但結果將被扔掉。如果這是一個無阻塞的未來(例如,博客文章中的'val timeoutFuture = akka.pattern.after(500.milliseconds,using = system.scheduler){...}',那麼我認爲這不是問題(它不會阻塞線程)。 –