Runnable不能返回结果、不能抛出受检异常;Callable可以返回泛型结果、能抛出任意异常。前者适用于日志记录等无反馈场景,后者适用于计算任务、远程调用等需结果与异常处理的场景。

Callable 和 Runnable 最核心的区别是:Runnable 不能返回结果、不能抛出受检异常;Callable 可以返回结果、能抛出受检异常。这个差异直接决定了它们在不同场景下的适用性。
返回值能力不同
Runnable 的 run() 方法返回 void,执行完没有结果可获取;Callable 的 call() 方法有泛型返回值(比如 Callable
- 适合用 Runnable:日志记录、定时清理、简单异步通知等无需反馈的场景
- 适合用 Callable:计算密集任务(如数值运算、数据转换)、远程调用封装、需要判断执行成功与否并取结果的场景
异常处理机制不同
Runnable 的 run() 方法只能抛出运行时异常(RuntimeException 及其子类);Callable 的 call() 方法可以声明抛出任意异常(包括 IOException、SQLException 等受检异常)。
- 如果任务逻辑可能触发文件读写、网络请求、数据库操作等易出错操作,Callable 更自然——异常可原样向上抛出,由调用方统一处理
- 用 Runnable 实现类似逻辑,就得在内部 try-catch 后转为 RuntimeException 包装,丢失原始异常类型信息
使用方式与执行环境不同
Runnable 可直接传给 Thread 构造器启动;Callable 不能直接交给 Thread,必须配合 ExecutorService 使用,通过 submit() 返回 Future 对象来获取结果或控制生命周期。
立即学习“Java免费学习笔记(深入)”;
- Thread t = new Thread(new MyRunnable()); → 合法
- Thread t = new Thread(new MyCallable()); → 编译错误
- Future
f = executor.submit(new MyCallable()); → 正确用法
实际选型建议
不追求结果、不涉及受检异常 → 优先用 Runnable,轻量简洁;需要结果、要处理 IO/SQL 等异常、需超时控制或取消任务 → 选 Callable + Future/CompletableFuture。
基本上就这些。两者不是替代关系,而是分工明确:Runnable 做“事”,Callable 做“有结果的事”。










