继承Thread类时,run()方法不能声明抛出受检异常,必须在内部用try-catch处理;运行时异常可不捕获但建议捕获;推荐用Runnable/Callable配合ExecutorService替代直接继承Thread。

继承 Thread 类时,run() 方法不能声明抛出受检异常(checked exception),这是 Java 语言规范决定的——因为 Thread.run() 的签名是 public void run(),没有 throws 子句。所以你无法在 run() 中直接向上抛出受检异常,必须在方法内部捕获并处理。
必须在 run() 内部捕获受检异常
如果你的业务逻辑可能抛出 IOException、SQLException 等受检异常,不能写成:
public void run() throws IOException { ... } —— 编译不通过。
正确做法是用 try-catch 包裹可能出异常的代码:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 把所有可能抛出受检异常的操作放在
try块中 - 在
catch中做具体处理:记录日志、设置错误状态、调用回调等 - 不要空 catch(即
catch (Exception e) {}),否则异常会静默丢失
运行时异常可选择性捕获
RuntimeException 及其子类(如 NullPointerException、IllegalArgumentException)是不受检的,run() 方法允许它们未被捕获而直接抛出。但实际开发中建议主动捕获:
- 未捕获的运行时异常会导致线程突然终止,且默认只打印堆栈到
System.err,容易被忽略 - 可通过
Thread.setDefaultUncaughtExceptionHandler()设置全局兜底处理器 - 更推荐在
run()开头加一层try-catch(Throwable),统一记录和响应
传递异常信息给外部的常用方式
由于 run() 无法返回值或抛出异常,若主线程需要知道子线程是否执行失败,需主动设计通信机制:
- 定义一个成员变量(如
private volatile Throwable error),在catch中赋值 - 提供
getError()方法供调用方检查 - 配合
join()等待线程结束后再读取结果 - 更现代的方式是改用
Callable<T>+Future,它天然支持异常传播(future.get()会重新抛出执行中的异常)
推荐替代方案:优先使用 Runnable 或 Callable
直接继承 Thread 并不灵活,也违背“组合优于继承”原则。多数场景应:
- 实现
Runnable(适合无返回、不抛受检异常的逻辑) - 实现
Callable<T>(适合需返回结果或可能抛异常的逻辑) - 用
ExecutorService管理线程,而非手动start() -
Callable的异常会被封装进ExecutionException,调用Future.get()时可统一捕获处理

















