示例代碼:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class AudienceLimitExcption extends Exception {
public AudienceLimitExcption(String message, Throwable cause) {
super(message, cause);
}
}
class Task implements Callable {
@Override
public Object call() throws Exception {
try {
System.out.println(1 / 0);
} catch (Exception e) {
throw new AudienceLimitExcption("limit error", e);
}
return 1;
}
}
代碼異常1:
public class Main {
public static void main(String[] args) {
Object r = null;
ExecutorService es = Executors.newFixedThreadPool(4);
try {
Future f = es.submit(new Task());
r = f.get();
System.out.println();
} catch (Throwable e) {
System.out.println(e.getClass());
}
}
}
輸出結果:class java.util.concurrent.ExecutionException 不是最真實的底層拋出去的異常。
分析異常棧:
會發現當cause==當前異常時候就是最真實異常,於是代碼如下:
public class Main {
public static void main(String[] args) {
Object r = null;
ExecutorService es = Executors.newFixedThreadPool(4);
try {
Future f = es.submit(new Task());
r = f.get();
System.out.println();
} catch (Throwable e) {
while (e != null) {
Throwable cause = e.getCause();
if (e.equals(cause)) {
System.out.println(e);
}
e = cause;
}
}
}
}
運行發現沒有輸出,debug發現當e爲真實異常時候,e.getCause方法返回值爲null。因此if分支無法爲true,所以沒有輸出。與上圖異常棧分析結論相悖,只能查看一下getCause方法實現:
public synchronized Throwable getCause() {
return (cause==this ? null : cause);
}
JDK實現時候,當cause等於當前異常e時候直接返回null,因此正確方案如下:
public class Main {
public static void main(String[] args) {
Object r = null;
ExecutorService es = Executors.newFixedThreadPool(4);
try {
Future f = es.submit(new Task());
r = f.get();
System.out.println();
} catch (Throwable e) {
while (e != null) {
Throwable cause = e.getCause();
if (cause == null) {
System.out.println(e.getClass());
}
e = cause;
}
}
}
}
輸出結果也就是1/0最真實的異常類型:class java.lang.ArithmeticException