陷阱 - 捕獲 InterruptedException
正如已經在其他陷阱中指出的那樣,通過使用捕獲所有異常
try {
// Some code
} catch (Exception) {
// Some error handling
}
有很多不同的問題。但是一個特別的問題是它可能導致死鎖,因為它在編寫多執行緒應用程式時會破壞中斷系統。
如果你開始一個執行緒,你通常還需要能夠出於各種原因突然停止它。
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
//Do something indefinetely
}
}
}
t.start();
//Do something else
// The thread should be canceld if it is still active.
// A Better way to solve this is with a shared variable that is tested
// regularily by the thread for a clean exit, but for this example we try to
// forcibly interrupt this thread.
if (t.isAlive()) {
t.interrupt();
t.join();
}
//Continue with program
t.interrupt()
將在該執行緒中引發 InterruptedException,而不是用於關閉執行緒。但是如果 Thread 需要在完全停止之前清理一些資源呢?為此,它可以捕獲 InterruptedException 並進行一些清理。
Thread t = new Thread(new Runnable() {
public void run() {
try {
while (true) {
//Do something indefinetely
}
} catch (InterruptedException ex) {
//Do some quick cleanup
// In this case a simple return would do.
// But if you are not 100% sure that the thread ends after
// catching the InterruptedException you will need to raise another
// one for the layers surrounding this code.
Thread.currentThread().interrupt();
}
}
}
但是如果你的程式碼中有一個 catch-all 表示式,那麼 InterruptedException 也會被它捕獲,並且中斷將不會繼續。在這種情況下會導致死鎖,因為父執行緒無限期地等待這個 thead 用 t.join()
停止。
Thread t = new Thread(new Runnable() {
public void run() {
try {
while (true) {
try {
//Do something indefinetely
}
catch (Exception ex) {
ex.printStackTrace();
}
}
} catch (InterruptedException ex) {
// Dead code as the interrupt exception was already caught in
// the inner try-catch
Thread.currentThread().interrupt();
}
}
}
因此最好單獨捕獲 Exceptions,但如果你堅持使用 catch-all,至少事先單獨捕獲 InterruptedException。
Thread t = new Thread(new Runnable() {
public void run() {
try {
while (true) {
try {
//Do something indefinetely
} catch (InterruptedException ex) {
throw ex; //Send it up in the chain
} catch (Exception ex) {
ex.printStackTrace();
}
}
} catch (InterruptedException ex) {
// Some quick cleanup code
Thread.currentThread().interrupt();
}
}
}