1. 程式人生 > >Java中斷異常 InterruptedException 的正確處理方式

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

你看到這篇檔案可能是因為你已經呼叫了一個丟擲 InterruptedException 異常的方法,並且需要以某種方式處理它。

首先,需要了解為一個方法為啥會 throws InterruptedException, 是這個方法丟擲中斷異常作為方法簽名的一部分以及呼叫正在呼叫的方法的可能結果。因此,首先要接受一個事實,InterruptedException 是這個方法呼叫的完全有效的結果。

現在,如果你正在呼叫的方法丟擲此類異常,你的方法應該怎麼做?可以通過考慮以下問題找出答案:

你正在實現的方法是否有意義丟擲異常 InterruptedException?換句話說,InterruptedException 異常是否是呼叫你的方法是一個明智的結果?

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

示例: 你的方法等待來自網路的值以完成計算並返回結果。如果阻塞網路呼叫丟擲 InterruptedException方法無法以正常方式完成計算。你讓 InterruptedException 傳播。

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),或者按照說的上面的第二種方法。

還有一個:呼叫 Thread.sleep
你正在嘗試讀取檔案,規範說你應該嘗試10次,間隔1秒。呼叫 Thread.sleep(1000)。所以,你需要處理 InterruptedException。對於一種方法 tryToReadFile 來說,如果說“如果我被打斷了,我無法完成嘗試閱讀檔案的行為”這一方法非常有意義。換句話說,它對丟擲的方法很有意義InterruptedExceptions。

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