Java多线程场景下,线程内部的异常如果未被正确捕获,默认会直接抛出到控制台,不会触发主线程的异常捕获逻辑,因此需要针对性地采用不同的处理方式。
普通线程的异常处理方式
1. 在run方法内部捕获异常
最基础的处理方式是在run方法的内部使用try-catch块捕获异常,这种方式可以处理线程执行过程中抛出的所有受检异常和非受检异常。
public class ThreadExceptionDemo {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
// 模拟线程执行逻辑
int a = 1 / 0;
} catch (Exception e) {
System.out.println("线程内部捕获到异常:" + e.getMessage());
}
});
thread.start();
}
}
2. 使用UncaughtExceptionHandler全局处理
如果线程内部没有捕获异常,可以通过设置UncaughtExceptionHandler来统一处理未捕获的异常,该处理器可以设置在线程级别或者线程组级别。
public class UncaughtExceptionHandlerDemo {
public static void main(String[] args) {
// 创建线程时设置异常处理器
Thread thread = new Thread(() -> {
int a = 1 / 0;
});
thread.setUncaughtExceptionHandler((t, e) -> {
System.out.println("线程" + t.getName() + "抛出未捕获异常:" + e.getMessage());
});
thread.start();
// 设置默认全局异常处理器
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
System.out.println("全局处理器捕获线程" + t.getName() + "的异常:" + e.getMessage());
});
Thread thread2 = new Thread(() -> {
int b = 1 / 0;
});
thread2.start();
}
}
线程池的异常处理方式
1. 使用Callable+Future捕获异常
如果使用Callable作为线程池的任务,可以通过Future的get方法获取执行结果,同时捕获任务抛出的异常。
import java.util.concurrent.*;
public class ThreadPoolCallableDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> {
int a = 1 / 0;
return "执行完成";
});
try {
String result = future.get();
System.out.println(result);
} catch (InterruptedException e) {
System.out.println("线程被中断:" + e.getMessage());
} catch (ExecutionException e) {
System.out.println("任务执行抛出异常:" + e.getCause().getMessage());
} finally {
executor.shutdown();
}
}
}
2. 自定义线程工厂设置异常处理器
可以在创建线程池时自定义线程工厂,为线程池中的每个线程设置UncaughtExceptionHandler,处理未捕获的异常。
import java.util.concurrent.*;
public class ThreadPoolFactoryDemo {
public static void main(String[] args) {
ThreadFactory threadFactory = r -> {
Thread thread = new Thread(r);
thread.setUncaughtExceptionHandler((t, e) -> {
System.out.println("线程池线程" + t.getName() + "异常:" + e.getMessage());
});
return thread;
};
ExecutorService executor = new ThreadPoolExecutor(
1,
1,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
threadFactory
);
executor.execute(() -> {
int a = 1 / 0;
});
executor.shutdown();
}
}
不同处理方式的选择建议
如果是单个线程的简单场景,优先在run方法内部捕获异常,逻辑更清晰;如果是多个线程需要统一的异常处理逻辑,使用UncaughtExceptionHandler可以减少重复代码;如果是线程池场景,需要根据任务类型选择,Callable任务用Future捕获,Runnable任务可以结合自定义线程工厂设置处理器。
| 场景 | 推荐处理方式 | 适用情况 |
|---|---|---|
| 普通单线程 | run方法内部try-catch | 线程逻辑简单,异常需要即时处理 |
| 多个普通线程 | UncaughtExceptionHandler | 多个线程需要统一的异常处理规则 |
| 线程池Callable任务 | Future.get捕获ExecutionException | 需要获取任务返回结果,同时处理异常 |
| 线程池Runnable任务 | 自定义线程工厂设置处理器 | 任务不需要返回结果,统一处理未捕获异常 |
Java线程多线程异常捕获UncaughtExceptionHandler线程池异常处理run方法异常修改时间:2026-07-18 09:21:26