本文是 Java 面向对象程序设计课程的课后作业详细讲解 Java 中两种最基础的线程创建方式继承 Thread 类与实现 Runnable 接口。通过代码示例、经典售票案例和多维度对比深入分析两者的本质区别、各自的优缺点以及实际开发中的选择原则。文章目录一、Java 创建线程的两种基础方式二、两种方式的代码实现2.1 方式一继承 Thread 类2.2 方式二实现 Runnable 接口三、核心区别多维度对比3.1 对比总表3.2 详细解读1. 单继承限制最本质区别2. 资源共享能力❌ 继承 Thread 实现需要用静态变量共享✅ 实现 Runnable天然共享3. 代码解耦与复用4. 与线程池的兼容性四、开发中如何选择推荐原则行业共识五、学习总结一、Java 创建线程的两种基础方式在 Java 中创建线程最常用的有两种方式继承java.lang.Thread类重写run()方法实现java.lang.Runnable接口实现run()方法再将其作为参数传给 Thread 对象很多初学者会疑惑两种方式都能创建线程它们到底有什么区别为什么老师总说推荐使用Runnable接口下面我们通过代码和案例逐一分析。二、两种方式的代码实现2.1 方式一继承 Thread 类实现步骤定义一个类继承Thread类重写run()方法编写线程执行的任务逻辑创建该子类的实例对象调用start()方法启动线程/** * 方式一继承Thread类创建线程 */publicclassMyThreadextendsThread{// 构造方法设置线程名publicMyThread(Stringname){super(name);}// 重写run方法编写线程任务Overridepublicvoidrun(){for(inti0;i5;i){System.out.println(Thread.currentThread().getName() 执行i);try{// 模拟线程执行耗时Thread.sleep(200);}catch(InterruptedExceptione){e.printStackTrace();}}}// 测试publicstaticvoidmain(String[]args){// 创建两个线程对象MyThreadt1newMyThread(线程A);MyThreadt2newMyThread(线程B);// 启动线程注意调用start()才会启动新线程调用run()只是普通方法调用t1.start();t2.start();}}2.2 方式二实现 Runnable 接口实现步骤定义一个类实现Runnable接口实现run()方法编写线程执行的任务逻辑创建该实现类的实例将实例作为参数传入Thread的构造方法创建 Thread 对象调用 Thread 对象的start()方法启动线程/** * 方式二实现 Runnable 接口创建线程 */publicclassMyRunnableimplementsRunnable{// 实现run方法编写线程任务Overridepublicvoidrun(){for(inti0;i5;i){System.out.println(Thread.currentThread().getName() 执行i);try{Thread.sleep(200);}catch(InterruptedExceptione){e.printStackTrace();}}}// 测试publicstaticvoidmain(String[]args){// 创建任务对象MyRunnabletasknewMyRunnable();// 将任务对象传给Thread创建多个线程执行同一个任务Threadt1newThread(task,线程A);Threadt2newThread(task,线程B);t1.start();t2.start();}}注意Runnable接口只有一个run()方法它本身不具备启动线程的能力最终还是要靠Thread类的start()方法来启动线程。Runnable的作用是封装线程要执行的任务。三、核心区别多维度对比3.1 对比总表对比维度继承 Thread 类实现 Runnable 接口本质继承一个线程类实现一个任务接口单继承限制受 Java 单继承限制子类不能再继承其他类不受单继承限制还可以同时继承其他类、实现其他接口资源共享多个线程间难以共享资源需借助静态变量天然支持多个线程共享同一个任务对象中的资源代码耦合度线程对象和任务逻辑绑定在一起耦合度高任务逻辑与线程对象分离解耦性好代码复用性任务只能被该线程类使用复用性差任务可以被多种线程、线程池复用复用性强线程池支持不支持直接放入线程池执行完美兼容线程池是实际开发的标准用法适用场景简单的单线程场景、无需共享资源的场景多线程共享资源、复杂业务、实际项目开发3.2 详细解读1. 单继承限制最本质区别Java 是单继承语言一个类只能有一个直接父类。如果选择继承Thread类那么这个类就不能再继承其他任何类了这会大大限制类的扩展性。而实现Runnable接口完全没有这个问题一个类可以同时实现多个接口还可以继承其他父类灵活性更高。2. 资源共享能力这是两者最直观的区别。实现 Runnable 接口可以很方便地让多个线程共享同一份资源而继承 Thread 类做不到这一点。我们用经典的“多窗口售票”案例来演示案例需求3 个窗口同时卖 100 张票总票数是共享的。❌ 继承 Thread 实现需要用静态变量共享publicclassTicketThreadextendsThread{// 必须用 static 静态变量才能让多个线程对象共享privatestaticinttickets100;publicTicketThread(Stringname){super(name);}Overridepublicvoidrun(){while(tickets0){System.out.println(getName() 卖出第 tickets-- 张票);try{Thread.sleep(10);}catch(InterruptedExceptione){e.printStackTrace();}}}publicstaticvoidmain(String[]args){// 每个线程对象都有自己的成员变量必须靠 static 共享newTicketThread(窗口1).start();newTicketThread(窗口2).start();newTicketThread(窗口3).start();}}✅ 实现 Runnable天然共享publicclassTicketRunnableimplementsRunnable{// 普通成员变量即可多个线程共享同一个对象privateinttickets100;Overridepublicvoidrun(){while(tickets0){System.out.println(Thread.currentThread().getName() 卖出第 tickets-- 张票);try{Thread.sleep(10);}catch(InterruptedExceptione){e.printStackTrace();}}}publicstaticvoidmain(String[]args){// 只创建一个任务对象交给3个线程执行TicketRunnabletasknewTicketRunnable();newThread(task,窗口1).start();newThread(task,窗口2).start();newThread(task,窗口3).start();}}对比结论继承 Thread 的方式必须借助static静态变量才能共享资源而静态变量生命周期长容易带来其他问题实现 Runnable 的方式只需要创建一个任务对象多个线程共享该对象的成员变量更加自然合理3. 代码解耦与复用继承Thread线程对象和任务逻辑绑定死了一个线程类只能做一件事复用性差实现Runnable把「线程要执行的任务」单独封装成一个对象和线程本身解耦。同一个任务可以交给不同的线程执行也可以交给线程池执行复用性极强4. 与线程池的兼容性在实际企业开发中我们几乎不会手动 new Thread而是使用线程池来管理线程。而线程池只能接收Runnable或Callable类型的任务不能直接接收 Thread 子类。从这一点来说实现 Runnable 接口是工业界的标准做法而继承 Thread 更多只出现在入门教学中。四、开发中如何选择推荐原则优先选择实现 Runnable 接口这是绝大多数场景下的最佳选择尤其是在需要多线程共享资源、需要良好扩展性、或者配合线程池使用的场景。什么时候可以用继承 Thread非常简单的单线程场景只是为了快速测试该类本身就是一个线程实体不需要再继承其他类教学演示、入门练习行业共识在真实的 Java 后端开发中99% 的场景都会使用 Runnable或 Callable来定义线程任务配合线程池来执行。直接继承 Thread 类创建线程的写法几乎不会出现在生产代码中因为它的扩展性差、资源浪费严重也不利于线程管理。五、学习总结通过这次作业我搞懂了继承Thread和实现Runnable这两种创建线程方式的区别。以前只知道两种写法都能运行线程不知道背后的设计思想和适用场景差异这么大。我最大的收获有两点面向接口编程的优势Runnable接口完美体现了面向接口编程的思想它把「线程执行的任务」和「线程本身」分离开带来了更好的扩展性、复用性和解耦性。资源共享的设计差异通过售票案例的对比我直观地感受到了两种方式在资源共享上的区别也理解了为什么实际开发都推荐用Runnable。如果觉得这篇文章对你有帮助欢迎点赞、收藏、关注有任何问题可以在评论区留言交流~