Thread.run() / Runnable.run() 未聲明拋出受檢異常RuntimeException、Error)會導致線程終止,但主線程無法捕獲,不影響其他線程public class Test2 {
public static void main(String[] args) throws InterruptedException {
try {
new A("異常線程").start();
} catch (RuntimeException re) {
System.out.println("主線程捕獲到子線程異常:"); // 永不執行
re.printStackTrace();
}
Thread.sleep(5);
System.out.println("主線程照常執行"); // 子線程終止不影響主線程
}
}
class A extends Thread {
A(String name) { super(name); }
public void run() {
System.out.println("run() 方法運行...");
for (int i = 0; i < 10; i++) {
System.out.println(getName() + " 輸出:" + i);
if (i == 3) {
throw new RuntimeException("run 內部拋出 Runtime 異常");
}
}
}
}
輸出:
run() 方法運行...
異常線程 輸出:0
異常線程 輸出:1
異常線程 輸出:2
異常線程 輸出:3
Exception in thread "異常線程" java.lang.RuntimeException: run 內部拋出 Runtime 異常
at testpack.A.run(Test2.java:26)
主線程照常執行
異常堆疊由 ThreadGroup.uncaughtException() 輸出,線程終止,主線程繼續。
JDK 1.5 引入靜態內部接口 Thread.UncaughtExceptionHandler,單方法:
void uncaughtException(Thread t, Throwable e)
thread.setUncaughtExceptionHandler(handler)ThreadGroup 實現 uncaughtException,可繼承重寫Thread.setDefaultUncaughtExceptionHandler(handler)ThreadGroup.uncaughtException()(中介,遞歸至父線程組)Thread.getDefaultUncaughtExceptionHandler()ThreadDeath 時,System.err 輸出線程名與堆疊,線程結束public class Test2 {
public static void main(String[] args) throws InterruptedException {
ExHandler eh1 = new ExHandler("Thread默認異常處理器");
ExHandler eh2 = new ExHandler("線程實例異常處理器");
Thread.setDefaultUncaughtExceptionHandler(eh1);
A a = new A("異常線程");
a.setUncaughtExceptionHandler(eh2); // 綁定實例處理器
a.start();
}
}
class A extends Thread {
A(String name) { super(name); }
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName() + " 輸出:" + i);
if (i == 3) { int x = 5 / 0; } // 拋出 ArithmeticException
}
}
}
class ExHandler implements Thread.UncaughtExceptionHandler {
private String name;
ExHandler(String name) { this.name = name; }
public void uncaughtException(Thread t, Throwable e) {
System.out.println("這是:" + name);
System.out.println("線程:" + t.getName() + " 異常:" + e.getMessage());
}
}
輸出(綁定實例處理器):
run() 方法運行... 異常線程 輸出:0 異常線程 輸出:1 異常線程 輸出:2 異常線程 輸出:3 這是:線程實例異常處理器 線程: 異常線程 異常: / by zero
註釋掉實例綁定後(走全局默認):
這是:Thread默認異常處理器 線程: 異常線程 異常: / by zero
run() 拋出受檢異常,內部轉為非受檢或妥善處理Future.get() 可獲取異常,或實現 ThreadFactory 統一設置處理器