孤舟笔记 并发篇十五 Thread和Runnable的区别是什么?面试必问的两种创建线程方式藏着大不同
文章目录一、先说结论Thread vs Runnable 核心对比二、两种方式怎么写继承 Thread实现 Runnable三、单继承Thread 的致命短板四、资源共享Runnable 的隐藏优势五、设计哲学解耦才是王道Thread vs Runnable 全景回答技巧与点评标准回答加分回答面试官点评个人网站学 Java 多线程第一课就是怎么创建线程。你肯定写过extends Thread和implements Runnable但面试官问你它俩到底有啥区别你可能只能说一个继承一个实现。再追问哪个更好为什么就卡壳了。今天咱们把 Thread 和 Runnable 的区别彻底讲透让你面试时不再含糊。一、先说结论Thread vs Runnable 核心对比维度说明Thread继承 Thread 类重写 run() 方法Runnable实现 Runnable 接口传入 Thread 构造器继承限制Thread 受单继承约束Runnable 无此限制资源共享Thread 方式各线程各有一份资源Runnable 可共享同一实例设计原则Runnable 符合组合优于继承解耦更好本质关系Thread 实现了 Runnable 接口Thread.run() 调用 target.run()一句话记住Thread 是继承当工人Runnable 是雇佣外包工——外包更灵活、更解耦、还能共享工具箱。二、两种方式怎么写继承 ThreadclassMyThreadextendsThread{Overridepublicvoidrun(){System.out.println(线程运行: getName());}}newMyThread().start();// 启动线程 实现 RunnableclassMyTaskimplementsRunnable{Overridepublicvoidrun(){System.out.println(线程运行: Thread.currentThread().getName());}}newThread(newMyTask()).start();// 把任务交给线程 看起来差不多区别藏在背后。三、单继承Thread 的致命短板Java只允许单继承。你继承了 Thread就不能再继承其他类了。这就好比你去一家公司当了正式员工继承就没法同时去另一家公司当正式员工了。但如果你是外包实现 Runnable可以同时接好几家的活。// ❌ 想继承另一个类没门classMyThreadextendsThread,SomeService{}// 编译错误// ✅ Runnable 随便继承classMyTaskextendsSomeServiceimplementsRunnable{}// 没问题 实际开发中你的任务类往往还需要继承业务基类选 Thread 就把自己堵死了。四、资源共享Runnable 的隐藏优势多个 Thread 线程之间无法直接共享实例变量而 Runnable 可以// Runnable 方式多个线程共享同一个 ticket实例classTicketimplementsRunnable{privateintcount5;Overridepublicvoidrun(){while(count0){System.out.println(Thread.currentThread().getName() 售出第 count-- 张票);// 共享 count}}}TicketticketnewTicket();newThread(ticket,窗口1).start();newThread(ticket,窗口2).start();// 两个窗口卖同一批票 如果用继承 Thread 的方式每个线程各有一个 count 副本各卖各的——就像两个窗口各拿 5 张票而不是共享 5 张。生活类比Runnable 是几个售票员共用一个票箱Thread 是每个售票员各背一个票箱。五、设计哲学解耦才是王道从设计角度看Thread 是线程本身Runnable 是任务本身。把做什么和谁来执行分开才是好的设计。// Thread 的 run() 和线程绑定在一起// 如果你想换一种执行方式比如线程池就得改代码// Runnable 和执行方式无关ExecutorServicepoolExecutors.newFixedThreadPool(3);pool.submit(newMyTask());// 同一个任务换线程池执行 这也符合单一职责原则Thread 只负责执行Runnable 只负责逻辑。Thread vs Runnable 全景Thread vs Runnable 全景 核心区别 ├── 继承方式Thread 单继承受限Runnable 接口灵活 ├── 资源共享Thread 各自为战Runnable 共享实例 └── 设计解耦Thread 任务与线程耦合Runnable 职责分离 本质关系 Thread implements Runnable ├── Thread.run() → if (target ! null) target.run() └── target 就是传入的 Runnable 实例 最佳实践 优先使用 Runnable或 Callable ├── 不受单继承限制 ├── 天然支持资源共享 ├── 任务与执行解耦 └── 兼容线程池Executor 框架 口诀继承 Thread 受限制实现 Runnable 更灵活 单继承是硬伤共享资源靠接口 任务线程要解耦优先 Runnable 记心头。回答技巧与点评标准回答Thread 和 Runnable 是 Java 创建线程的两种方式。继承 Thread 需要重写 run() 方法实现 Runnable 需要将实例传入 Thread 构造器。核心区别有三点一是 Thread 受 Java 单继承限制Runnable 是接口更灵活二是 Runnable 可以让多个线程共享同一个实例的资源三是 Runnable 将任务逻辑与线程执行解耦符合单一职责原则也更兼容线程池。实际开发中推荐优先使用 Runnable。加分回答揭示本质Thread 本身就实现了 Runnable 接口Thread 的 run() 方法内部会判断是否有 target即传入的 Runnable有则调用 target.run()没有才执行自身重写的 run()。所以继承 Thread 重写 run()本质上是覆写了分发逻辑而实现 Runnable走的是正常的任务分发提到 CallableRunnable 的 run() 没有返回值、不能抛受检异常JDK 1.5 引入了 Callable 接口弥补这个不足配合 Future 可以获取执行结果。这是 Runnable 的升级版线程池的统一抽象Executor 框架只认 Runnable和 Callable不认 Thread。使用 Runnable 可以无缝切换到线程池执行而继承 Thread 的方式就做不到了面试官点评这道题看似简单实则考察你对面向对象设计的理解。只说一个继承一个实现只是表面能讲出单继承限制、资源共享差异、解耦设计原则才算及格。如果还能提到 Thread 实现了 Runnable 的本质关系、Callable 的扩展、以及线程池的统一抽象面试官会认为你不仅会用还懂得背后的设计哲学。原文阅读内容有帮助点赞、收藏、关注三连评论区等你