2012-10-10 111 views
13

什麼是處理InterruptedException S IN番石榴使用Throwables.propagate(E)時,最好的做法?番石榴:Throwables.propagate和InterruptedException的

我喜歡使用throw Throwables.propagate(e),尤其是在沒有拋出檢查的異常並在異常處理是調用者的責任的方法。但它並沒有做到我期望的InterruptedException。

我不想失去該線程被中斷的事實,所以我寫出來的東西,如:

public void run() { 
    Callable c = ...; 
    try { 
     c.call(); 
    } catch (InterruptedException e) { 
     Thread.currentThread().interrupt(); 
     throw Throwables.propagate(e); 
    } catch (Exception e) { 
     throw Throwables.propagate(e); 
    } 
} 

有沒有辦法在番石榴做到這一點?是否有(向後兼容的?!)方式使用類似Throwables.propagate()的方法將線程設置爲中斷,如果它包裝並傳播InterruptedException?

+1

我會提出這個作爲內番石榴 – artbristol

回答

7

方便的是,我們在內部討論了一段時間。我只是複製和粘貼:

我強硬的Throwables.propagate(e)的看法是,它基本上throw new RuntimeException(e)和人們通常不應該這樣做,只是因爲他們通常不應該寫throw new RuntimeException(e)。 (如果他們要寫它,他們不妨直接寫下來,這樣很清楚發生了什麼)。

我對catch (Exception e)的強硬看法 - 通常是人們如何陷入混亂 - 是他們通常不應該這樣做。 (很明顯,有些情況下catch (Exception e)顯然是正確的做法(基本上任何頂級的操作範圍catch塊),但這些都是......顯而易見的。)

我對InterruptedException的強硬意見是具有InterruptedException實施Exception完全是這樣破壞的:它需要特殊處理,其他例外不需要。

我強硬的轉換InterruptedExceptionRuntimeException意見是「不」。 (這和我上面說的很多其他東西一樣,是有爭議的。)

所以一方面,我不確定我們能做些什麼來挽救propagate()。另一方面,也許讓這個方法不那麼糟糕是件好事。

話又說回來,考慮這個調用者,後者抓住ExecutionException e

throw Throwables.propagate(e.getCause());

這將是錯誤中斷消費者線程,只是因爲它是錯誤的直接扔e.getCause(),因爲中斷之意對於計算線程而言,不是消費者線程。

我傾向於單獨離開propagate()。 (正如你可能已經猜到了,我個人傾向於貶低它,但是這是一個更大的討論。)

+1

+1有趣點的功能要求。我很驚訝人們寫'throw Throwables.propagate(e.getCause());'!堆棧跟蹤看起來像在單個線程中發生的一切! – artbristol

+1

謝謝,有趣的一點。 +1給InterruptedException實現異常是錯誤的,但Java是它在哪裏。 我認爲將InterruptedException轉換爲RuntimeException有時很重要:如果我的方法簽名由外部接口修復(所以我不能拋出InterruptedException),並且我的操作被中斷(所以我無法履行合同),我必須拋出異常。除了將線程設置爲中斷並拋出RuntimeException之外,還有什麼其他明智的選擇? –

+4

爲了編寫'throw new RuntimeException(e)',讓異常包裝異常(特別是當沒有添加任何有用的東西,例如關於當前上下文的附加消息)時,會產生惱人的噪音。無論哪裏都可以避免噪音(例如,它已經是一個不受檢查的例外),那麼很好。 有一種思想,API應儘可能使用未經檢查的異常。即使不買這種說法,仍然需要實現以這種方式編寫的其他人的界面。 所以請不要棄用'Throwables.propagate(e)'! –