线程中异常无法被直接捕获,需通过UncaughtExceptionHandler、全局处理器、Callable与Future或自定义线程工厂处理,确保异常不被忽略。

在Java中,线程中抛出的异常不能被创建该线程的方法直接通过 try-catch 捕获。这是因为每个线程有独立的调用栈,主线程无法捕获子线程中的异常。要正确处理线程中的异常,需要使用特定机制。
1. 使用 UncaughtExceptionHandler
每个线程都可以设置一个未捕获异常处理器(UncaughtExceptionHandler),当线程执行过程中抛出未被捕获的异常时,会自动调用该处理器。
Thread thread = new Thread(() -> {
// 模拟异常
throw new RuntimeException("线程内发生异常");
});
// 为线程设置异常处理器
thread.setUncaughtExceptionHandler((t, e) -> {
System.out.println("线程 " + t.getName() + " 抛出了异常: " + e.getMessage());
});
thread.start();
这种方式适用于继承 Thread 类或实现 Runnable 接口的场景。
立即学习“Java免费学习笔记(深入)”;
2. 全局默认异常处理器
可以为所有未设置处理器的线程设置一个默认的全局处理器:
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
System.out.println("全局捕获:线程 " + t.getName() + " 发生异常 - " + e.getMessage());
});
Thread thread = new Thread(() -> {
throw new IllegalStateException("测试全局处理器");
});
thread.start(); // 使用默认处理器
3. 使用 Callable 和 Future 捕获异常
如果使用线程池,推荐使用 Callable 而不是 Runnable。Callable 的 call() 方法可以抛出异常,并通过 Future.get() 捕获。
ExecutorService executor = Executors.newSingleThreadExecutor();Future
future = executor.submit(() -> { // 会抛出异常 throw new Exception("Callable 中的异常"); }); try { future.get(); // get() 会重新抛出执行异常 } catch (Exception e) { System.out.println("捕获到任务异常: " + e.getCause().getMessage()); }
executor.shutdown();
注意:future.get() 抛出的是 ExecutionException,真正的异常在 getCause() 中。
4. 自定义线程工厂统一设置处理器
在线程池中,可以通过自定义 ThreadFactory 统一为所有线程设置异常处理器:
ThreadFactory factory = r -> {
Thread t = new Thread(r);
t.setUncaughtExceptionHandler((thread, e) ->
System.err.println("工厂创建的线程异常: " + e.getMessage())
);
return t;
};
ExecutorService executor = Executors.newFixedThreadPool(2, factory);
基本上就这些方法。选择哪种方式取决于你的使用场景:简单线程用 UncaughtExceptionHandler,线程池优先考虑 Callable + Future,或者统一通过线程工厂管理。关键是不要让异常在线程中“静默消失”。










