thread是线程本体,负责生命周期与资源管理;runnable是任务逻辑接口,只定义run()行为,需由thread或线程池执行,二者职责分离、不可互换。

直接说清楚:Thread 是“开车的人”,Runnable 是“要去哪儿、干啥活”的路线单——人可以换,路线单可以复用;但路线单自己不会动,也不会开车。
Thread 负责“怎么跑”,不是“跑什么”
Thread 类封装了操作系统线程的全部能力:创建、启动、暂停、中断、等待、销毁,还管栈空间、优先级、线程组这些底层资源。它内部有个 private Runnable target 字段,说明它本质是个“执行容器”,真正干活的逻辑不在它身上,而是在它持有的那个 Runnable 里。
你可以把它理解成一辆配齐油门、刹车、方向盘的汽车——但车本身不决定目的地,也不写导航路线。
Runnable 只回答“做什么”,不管“谁来做”
它只是一个接口,只有一行定义:void run();。没有 start()、没有 sleep()、不能被直接启动,甚至不能 new 出来(它是接口)。它只承诺:“我这里有一段逻辑,等谁来执行我。”
就像一张打印好的任务卡: - 卖10张电影票 - 下载一个文件 - 计算一段数据 这些事它都描述清楚了,但卡不会自己动,得交给 Thread 或线程池去跑。
为什么不能把 Runnable 当成“另一种线程写法”?
常见误解是“继承 Thread 和实现 Runnable 是两种并列写法”。其实不是——它们根本不在同一层:
- Thread 是具体类,有生命周期、系统资源、可调用 start()
- Runnable 是纯行为契约,无状态、无资源、不可启动
- 你写 new Thread(new MyTask()).start(),实际是:Thread 拿着 MyTask 这张任务卡,开动自己这辆车去执行
- 你写 new MyThreadSubclass().start(),其实是 Thread 自己“兼职”写了任务卡(重写了 run),但本质仍是 Thread 在执行
新手最容易踩的坑
两个典型错误,一试就露馅:
- 调用 myRunnable.run() —— 看似在跑任务,实则只是普通方法调用,全程都在主线程,完全没开新线程
- 多个继承 Thread 的子类实例共享变量失败 —— 因为每个子类对象都有独立的成员字段,不是真共享;而同一个 Runnable 实例被多个 Thread 执行,才天然共享状态
记住一句话:start() 是线程启动的唯一入口,run() 是任务执行的唯一出口。中间谁来调度、谁来承载、谁来复用,就看你是用 Thread 还是 Runnable 来组织代码。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











