我需要調用一個可能返回或不返回及時結果的服務。我希望能寫是否有一個標準的Scala函數用於運行帶超時的塊?
val result = runWithTimeout(5000, valReturnedOnTimeout) { service.fetch }
有沒有一個標準功能,將做的工作 - 像Ruby的timeout?
我需要調用一個可能返回或不返回及時結果的服務。我希望能寫是否有一個標準的Scala函數用於運行帶超時的塊?
val result = runWithTimeout(5000, valReturnedOnTimeout) { service.fetch }
有沒有一個標準功能,將做的工作 - 像Ruby的timeout?
以信譽其他的答案 - 在沒有任何標準庫函數,我已經走下了期貨路線。
import scala.concurrent._
import scala.concurrent.duration._
def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
Await.result(Future(f), timeMins milliseconds).asInstanceOf[Option[T]]
}
def runWithTimeout[T](timeoutMs: Long, default: T)(f: => T) : T = {
runWithTimeout(timeoutMs)(f).getOrElse(default)
}
這樣
@Test def test {
runWithTimeout(50) { "result" } should equal (Some("result"))
runWithTimeout(50) { Thread.sleep(100); "result" } should equal (None)
runWithTimeout(50, "no result") { "result" } should equal ("result")
runWithTimeout(50, "no result") { Thread.sleep(100); "result" } should equal("no result")
}
我會的任何反饋表示感謝,這是否是一個很好的斯卡拉風格!
我已經擴展了這個來處理異常在http://stackoverflow.com/questions/6229778 – 2011-06-06 08:10:58
您可以在一個新的線程中啓動它,然後等待它完成Thread.join。如果你傳遞一個參數來加入,它最多等待幾毫秒。
val t = new Thread {
override def run() {
//...
}
}
t.start()
t.join(5000)
謝謝,我也可以使用Executors框架。但我在檢查我是不是缺少內置或慣用的東西。 – 2011-06-03 13:46:52
你可以使用一個未來
import scala.actors.Futures._
val myfuture =
future {
Thread.sleep(5000)
println("<future>")
"future "
}
awaitAll(300,myfuture) foreach println _
但也看看Circuit Breaker for Scala是的 Circuit Breaker Pattern一個實現。基本上,它可以讓你控制超時,如果發生故障訪問外部資源
使用看起來像這樣在斯卡拉(自述)會發生什麼:
. . .
addCircuitBreaker("test", CircuitBreakerConfiguration(timeout=100,failureThreshold=10))
. . .
class Test extends UsingCircuitBreaker {
def myMethodWorkingFine = {
withCircuitBreaker("test") {
. . .
}
}
def myMethodDoingWrong = {
withCircuitBreaker("test") {
require(false,"FUBAR!!!")
}
}
}
我喜歡斷路器,但我想標準庫中沒有任何東西。我會盡量寫一些基於期貨的東西來保持簡單。 – 2011-06-03 15:06:17
請注意,未來阻塞線程。 http://stackoverflow.com/q/5646879/203968因此,多次呼叫您的客戶端可能會導致您的線程捱餓。因此斷路器。當你認爲通話不可能工作時,你可以「打破電路」 – oluies 2011-06-03 15:39:32
是的,我將不得不考慮這一點,因爲通話在我的網絡層,所以我可以每個瀏覽器都有一個。我可能必須讓瀏覽器輪詢並最終使用Executors。 – 2011-06-03 15:48:18
還沒有提到的東西是等待,這是一個關於actors包的Futures對象的方法。 awaitEither返回從第一一對期貨的結果來完成,因此,例如像這樣,可以使用:
awaitEither(future{task}, alarm(timeoutPeriod))
,然後在方法裝扮成提示:
def runWithTimeout[T](timeoutPeriod: Int, timeoutValue: T)(task: => T) = {
awaitEither(future{task}, alarm(timeoutPeriod)) match {case() => timeoutValue case x => x}
}
報警返回可賦值給Any類型的val的單元,因此awaitEither返回可與模式匹配的東西。
我認爲,當@ pr1001指出'報警',但認爲我們可能會最終開始另一個線程的報警 - 這似乎有點矯枉過正。它確實使一個很好的短暫的表達。 – 2011-06-03 21:36:19
是的,我知道使用Actor可以解決這個問題,但對於這樣一個簡單的問題似乎過度。 – 2011-06-03 13:33:35
相關http://stackoverflow.com/q/5797666/132374 – 2013-10-30 03:07:53