线程异常处理
Java中每个线程的异常处理是相互独立的,一个线程产生的异常不会影响其他线程的正常运行。因此,也不能在一个线程中catch另一个线程中抛出的异常。
例如,下面这段代码试图catch方法exceptionInThread()中的异常
public static void main(String[] args) {
try{
exceptionInThread();
} catch (Exception e) {
System.out.println("catch exception in the main thread");
}
}
public static void exceptionInThread() {
Thread t = new Thread(() -> {
throw new RuntimeException("something wrong in thread");
});
t.start();
}
但如下实际的运行结果可以发现异常并没有被catch住。

在Java中可以通过设置Thread.UncaughtExceptionHandler处理线程中的异常。例如下面的代码段中设置了线程的默认UncaughtExceptionHandler.
private static Thread.UncaughtExceptionHandler uncaughtExceptionHandler = (Thread t, Throwable e) -> {
StringBuilder sb = new StringBuilder();
sb.append("Thread name: ")
.append(t.getName())
.append(", caught exception: ")
.append(e.getClass())
.append(" [")
.append(e.getMessage())
.append("]");
System.out.println(sb.toString());
};
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
try{
exceptionInThread();
} catch (Exception e) {
System.out.println("catch exception in the main thread");
}
}
public static void exceptionInThread() {
Thread t = new Thread(() -> {
throw new RuntimeException("something wrong in thread");
});
t.start();
}
运行结果为:

线程池异常处理
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);对线程池中抛出的异常也有同样的效果。
完整代码段如下所示:
package examples;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MultilThreadExceptionHandler {
private static Thread.UncaughtExceptionHandler uncaughtExceptionHandler = (Thread t, Throwable e) -> {
StringBuilder sb = new StringBuilder();
sb.append("Thread name: ")
.append(t.getName())
.append(", caught exception: ")
.append(e.getClass())
.append(" [")
.append(e.getMessage())
.append("]");
System.out.println(sb.toString());
};
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
exceptionInThreadPool();
exceptionInThread();
}
public static void exceptionInThread() {
Thread t = new Thread(() -> {
throw new RuntimeException("something wrong in thread");
});
t.start();
}
public static void exceptionInThreadPool() {
ExecutorService threadPool = Executors.newFixedThreadPool(1 );
threadPool.execute(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
throw new RuntimeException("exception in runnable");
});
threadPool.shutdown();
}
}
TODO
在测试过程中发现,线程池中task通过threadPool.execute提交的runnable中的异常可以被UncaughtExceptionHandler正确处理,但通过threadPool.submit提交的callable中的异常却无法处理。需要进一步阅读源码了解其中机制。
网友评论