一、问题概述在 Java 中创建线程主要有两种经典方式继承Thread类创建它的子类对象实现Runnable接口再将实现类对象作为参数传入Thread类二、两种方式的代码实现示例1. 继承 Thread 类的方式// 1. 定义Thread的子类 public class MyThread extends Thread { // 2. 重写run()方法线程执行的逻辑写在这里 Override public void run() { for (int i 0; i 5; i) { System.out.println(Thread.currentThread().getName() 执行: i); } } public static void main(String[] args) { // 3. 创建线程对象并调用start()方法启动线程 MyThread thread1 new MyThread(); thread1.setName(继承Thread的线程); thread1.start(); } }2. 实现 Runnable 接口的方式// 1. 定义Runnable接口的实现类 public class MyRunnable implements Runnable { // 2. 实现run()方法线程执行的逻辑写在这里 Override public void run() { for (int i 0; i 5; i) { System.out.println(Thread.currentThread().getName() 执行: i); } } public static void main(String[] args) { // 3. 创建Runnable实现类对象 MyRunnable runnable new MyRunnable(); // 4. 将Runnable对象作为参数传入Thread类创建线程对象并启动 Thread thread2 new Thread(runnable, 实现Runnable的线程); thread2.start(); } }三、核心区别对比对比维度继承 Thread 类实现 Runnable 接口继承 / 实现关系类继承了Thread类Java 中类只能单继承因此该类无法再继承其他父类实现了Runnable接口不影响该类继承其他父类也可以同时实现多个接口代码复用性线程逻辑和线程对象绑定每次创建线程都需要新建子类对象复用性差线程逻辑Runnable实现类和线程对象Thread分离同一个Runnable对象可以被多个线程共享面向对象设计线程本身和线程任务强耦合不符合 “单一职责原则”线程任务和线程对象解耦任务逻辑可以被不同线程复用更符合面向对象的设计思想使用场景适用于简单的、一次性的线程任务且该类不需要继承其他类适用于复杂场景尤其是需要资源共享、多线程处理同一任务或类需要继承其他父类的情况资源共享能力多个线程对象独立无法直接共享成员变量除非使用 static 修饰多个Thread对象传入同一个Runnable对象可以直接共享Runnable中的成员变量四、关键细节与优缺点分析1. 继承 Thread 类的优缺点✅优点代码写法简单直接逻辑集中适合新手快速上手可以直接调用Thread类的方法如getName()、sleep()等无需额外获取线程对象❌缺点受限于 Java 单继承机制一旦继承了Thread类就无法再继承其他类比如Servlet、自定义业务类扩展性差线程任务和线程对象强绑定无法被多个线程共享同一任务逻辑复用性低2. 实现 Runnable 接口的优缺点✅优点不占用类的继承名额类可以自由继承其他父类扩展性强任务逻辑和线程对象分离同一个Runnable实现类可以被多个Thread对象使用支持资源共享比如多线程卖票场景更符合 “组合优于继承” 的设计原则代码的耦合度更低❌缺点代码相比继承方式稍显繁琐需要额外创建Runnable对象再传入Thread类无法直接调用Thread类的方法需要通过Thread.currentThread()获取当前线程对象后才能调用五、实战场景对比多线程卖票场景4 个窗口卖 10 张票1. 继承 Thread 类的实现有问题的版本public class TicketThread extends Thread { // 非静态变量每个线程对象都有独立的ticketCount private int ticketCount 10; Override public void run() { while (ticketCount 0) { System.out.println(getName() 卖出第 ticketCount 张票); ticketCount--; } } public static void main(String[] args) { // 创建4个线程对象每个对象都有自己的ticketCount TicketThread t1 new TicketThread(); TicketThread t2 new TicketThread(); TicketThread t3 new TicketThread(); TicketThread t4 new TicketThread(); t1.start(); t2.start(); t3.start(); t4.start(); } }❌问题每个线程对象都有自己的ticketCount最终会卖出 40 张票无法实现共享 10 张票的需求。如果要实现共享需要将ticketCount设为static但会导致类级别的变量共享容易引发线程安全问题。2. 实现 Runnable 接口的实现正确版本public class TicketRunnable implements Runnable { // 成员变量被所有传入同一个Runnable对象的线程共享 private int ticketCount 10; Override public void run() { while (true) { if (ticketCount 0) { System.out.println(Thread.currentThread().getName() 卖出第 ticketCount 张票); ticketCount--; } else { break; } } } public static void main(String[] args) { // 创建1个Runnable对象共享ticketCount TicketRunnable ticketTask new TicketRunnable(); // 4个线程传入同一个Runnable对象共享任务和资源 new Thread(ticketTask, 窗口1).start(); new Thread(ticketTask, 窗口2).start(); new Thread(ticketTask, 窗口3).start(); new Thread(ticketTask, 窗口4).start(); } }✅效果4 个线程共享同一个ticketCount变量最终只会卖出 10 张票完美实现了资源共享。六、总结与推荐优先推荐使用实现Runnable接口的方式它解决了 Java 单继承的限制实现了任务与线程的解耦支持资源共享扩展性和复用性更强是实际开发中的主流选择。继承Thread类的方式仅适用于简单的、无需扩展和共享的场景不推荐在复杂项目中使用。本质上Thread类本身也实现了Runnable接口所以两种方式最终都是通过Thread对象来启动线程的核心区别在于任务逻辑的组织方式。