Java中斷異常 InterruptedException 的正確處理方式

你看到這篇文件多是由於你已經調用了一個拋出 InterruptedException 異常的方法,而且須要以某種方式處理它。java

首先,須要瞭解爲一個方法爲啥會 throws InterruptedException, 是這個方法拋出中斷異常做爲方法簽名的一部分以及調用正在調用的方法的可能結果。所以,首先要接受一個事實,InterruptedException 是這個方法調用的徹底有效的結果。網絡

如今,若是你正在調用的方法拋出此類異常,你的方法應該怎麼作?能夠經過考慮如下問題找出答案:線程

你正在實現的方法是否有意義拋出異常 InterruptedException?換句話說,InterruptedException 異常是不是調用你的方法是一個明智的結果?code

  • 若是是,那麼 throws InterruptedException 應當成爲你的方法簽名,你應該讓異常傳播(即不捕獲該異常的話)。

示例: 你的方法等待來自網絡的值以完成計算並返回結果。若是阻塞網絡調用拋出 InterruptedException方法沒法以正常方式完成計算。你讓 InterruptedException 傳播。server

int computeSum(Server server) throws InterruptedException {
    // Any InterruptedException thrown below is propagated
    int a = server.getValueA();
    int b = server.getValueB();
    return a + b;
}
  • 若是不是,那麼你不該該聲明你的方法 throws InterruptedException, 你應該(必須!)捕獲異常。在這種狀況下,如今要記住兩件事:
  1. 有人打斷了你的線程。這我的可能急於取消操做,優雅地終止程序,或者其餘什麼。你應該對那我的保持禮貌而且不用再費力地從你的方法中返回。
  2. 即便你的方法能夠設法讓出現 InterruptedException 異常時, 即在線程被中斷的狀況下, 產生合理的返回值,線程被中斷過這件事仍然很重要。特別是,調用方法的代碼可能會對執行方法期間是否發生中斷感興趣。您應該經過設置中斷標誌來記錄發生中斷的事實:即須要在 catch 裏調用Thread.currentThread().interrupt() .

示例: 用戶要求打印兩個值的總和。若是沒法計算總和,則打印「沒法計算總和」(而且比因爲一個致使程序因堆棧跟蹤而崩潰要好得多 InterruptedException)。換句話說,用這個方法聲明這個方法是沒有意義的throws InterruptedException。接口

void printSum(Server server) {
    try {
        int sum = computeSum(server);
        System.out.println("Sum: " + sum);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();  // set interrupt flag
        System.out.println("Failed to compute sum");
    }
}

到目前爲止,應該清楚的是,作這件事throw new RuntimeException(e)是一個壞主意。這對調用者來講不太禮貌。您能夠發明一個新的運行時異常,但根本緣由(某人但願線程中止執行)可能會丟失。開發

另外一個例子:實施 Runnable
正如您可能已經發現的那樣,簽名 Runnable.run 不容許從新拋出 InterruptedExceptions。好吧,你聲明瞭實現 Runnable 接口,這意味着你已聲明處理可能的中斷異常問題。選擇不一樣的接口,例如Callable則能夠拋出中斷異常(V call() throws Exception),或者按照說的上面的第二種方法。get

還有一個:調用 Thread.sleep
你正在嘗試讀取文件,規範說你應該嘗試10次,間隔1秒。調用 Thread.sleep(1000)。因此,你須要處理 InterruptedException。對於一種方法 tryToReadFile 來講,若是說「若是我被打斷了,我沒法完成嘗試閱讀文件的行爲」這一方法很是有意義。換句話說,它對拋出的方法頗有意義InterruptedExceptions。io

String tryToReadFile(File f) throws InterruptedException {
    for (int i = 0; i < 10; i++) {
        if (f.exists())
            return readFile(f);
        Thread.sleep(1000);
    }
    return null;
}

做者:計算機科學

Andreas Lundblad,理論計算機科學博士。在Oracle開發Java平臺(javac,javadoc,sjavac)工做了三年。安德烈亞斯是StackOverflow的Java標籤的前10貢獻者.

相關文章
相關標籤/搜索