2015-05-01 73 views
4

這裏更常見的問題是:在生產質量代碼中,是否需要關注ExecutionContext或其他併發基礎結構產生的異常,而不是執行未來的主體?例如,如果線程池發生某些故障,我是否會看到由於它而未能執行的未來返回的異常?Future何時可以返回未從Future中拋出的Exception?

這反過來又引導瞭如何處理未來的錯誤處理。我在一般意見中指出,應該返回錯誤而不是拋出錯誤,無論是或scalactic的或。但是,如果在調用未來時需要考慮基礎架構的異常,即使其他所有內容都是以無例外或異常封裝的方式編寫的,但這似乎非常複雜。但我不會就此徵求意見 - 我認爲,這篇文章將被視爲「太廣泛」。 :=(

回答

3

是的,沒有......好的,也許我們需要詳細說明。

如果我們談論「生產質量代碼」,即代碼如果不起作用就會花費大量資金,但我們不能假設基礎架構(運行時,庫等)正常工作。因爲他們沒有。庫有錯誤,即使它們不影響我們,它們依賴於有限的資源,如內存,文件句柄以及併發的東西:線程。

因此,在某個時刻應該意識到的一件事是:即使是最微不足道的代碼行也可能會失敗。所以這是肯定的部分:是的,你應該關注這種可能性。

旁邊的任何部分:你寫

應退還

錯誤,而不是拋出,例如使用或者是scalactic或

對於您所期望的異常,這是正確的。事情很可能會失敗。在100000次以上的處決中,多說1次。 (是的,我把這個數字從我的帽子裏拿出來,我甚至沒有穿過)。在這種情況下,添加明確的異常處理是適當的,您提到的建議也適用。

但它不適用於所有其他可能的故障模式。如果你試圖用這種方法來處理它們,你將無法在所有異常處理之間找到你的主代碼。而且您可能會在此過程中添加大量的錯誤。

相反,有一些通用的策略來處理代碼中的任意異常。對於這些情況,異常是使用正確的工具。對於這個策略,簡單更好,因爲你真的不知道這個代碼會在什麼情況下執行。

Web應用程序中的典型方法是圍繞完整的請求嘗試一個catch塊,記錄異常並返回一些錯誤頁面。

更復雜的方法是像Akka這樣的Actor框架,它有Actor來完成工作。如果這樣的Actor引發異常,Actor將會死亡並被新的替換(用各種方式來控制確切的行爲)。

另一種方法,即獲取與上述兩種方法結合起來,是有不同的機器上應用程序的多個實例運行,所以一臺機器上的問題不會影響別人。

正如你所看到的方法來處理您的基礎架構中的例外,包括但不限於執行你的期貨庫是用於處理您的期貨的「正常」的失效模式的異常處理非常不同。

4

如果在執行Future但不是在它的身上,我不認爲這可能被認爲Future內返回的Future.apply實施提交PromiseCompletingRunnable執行人發生異常看起來。像這樣:

class PromiseCompletingRunnable[T](body: => T) extends Runnable { 
    val promise = new Promise.DefaultPromise[T]() 

    override def run() = { 
    promise complete { 
     try Success(body) catch { case NonFatal(e) => Failure(e) } 
    } 
    } 
} 

注意,底層Promise完成與使用try/catch塊執行的Future.apply主體應該異常上述Runnable(似乎並不可能),或執行程序內發生。在try/catch塊外面,它不會被包裝在返回的中。如果執行程序中出現某種異常,則更可能的情況是它是一些致命錯誤。更糟的是,這可能意味着Future將永遠不會完成。

如果它是一個導致問題的線程池,那麼除了找到一個更好的線程或識別底層問題(太多的線程?)之外,你可以做的事情真的不多。在運行時你可以做的更少(如果有的話)。真的,這意味着底層的併發API非常壞,使用的內存太多等等。

+0

我猶豫狡辯,但我沒有看到PromiseCompletingRunnable如何防止ExecutionContext(廣義上)將結果設置爲任何想要的。另一方面,考慮到其他答案和其他答案,我會感覺到我不需要太在意 - 只要我不寫自動駕駛儀或其他東西。 –

+0

@EdStaub PromiseCompletingRunnable中的'promise'是一個val,你不能嘗試多次完成'Promise'。所以一旦'run()'開始執行,執行者確實沒有辦法改變它的值。你可能會說執行者可能會先嚐試完成'Promise',但我不知道任何執行者甚至知道'Promise'甚至* *是什麼。所以從理論上講,一些自定義執行程序可以在執行前執行此操作,但實際上沒有。標準庫中的默認行爲不會這樣做,也不應該這樣做。 –

+0

謝謝。 FWIW,我主要關心run()根本無法執行的情況,並且執行程序可能會通過填寫自己的失敗來指示它。 –

相關問題