Java 创建线程:继承 Thread 子类 vs 实现 Runnable 接口
Java 创建线程继承 Thread 子类 vs 实现 Runnable 接口一、两种方式代码示例方式 1继承 Thread 类创建线程通过自定义类继承Thread重写run()方法调用start()启动线程。// 继承Thread子类 class MyThread extends Thread{ Override public void run() { System.out.println(线程正在执行任务); } } public class TestThread{ public static void main(String[] args) { MyThread t1 new MyThread(); t1.start(); } }方式 2实现 Runnable 接口创建线程自定义类实现Runnable接口把任务传入 Thread 对象再启动线程。// 实现Runnable接口 class MyTask implements Runnable{ Override public void run() { System.out.println(线程正在执行任务); } } public class TestRunnable{ public static void main(String[] args) { MyTask task new MyTask(); Thread t1 new Thread(task); t1.start(); } }二、核心区别对比1. 继承关系不同最大区别继承 Thread 类Java 是单继承一旦继承了Thread就不能再继承其他父类会限制代码的扩展性。实现 Runnable 接口只是实现接口当前类还可以继承别的父类更加灵活规避了单继承的限制。2. 任务资源共享能力不同继承 Thread 类每创建一个Thread子类对象都是独立的线程实例无法直接共享同一个任务资源必须借助静态变量才能实现共享。实现 Runnable 接口多个Thread对象可以传入同一个 Runnable 任务实例天然可以共享任务中的成员变量非常适合多线程售票、计数这类资源共享场景。资源共享示例Runnable 方式class TicketTask implements Runnable{ private int ticket 10; Override public void run() { while(ticket 0){ ticket--; System.out.println(Thread.currentThread().getName() 卖出一张票剩余ticket); } } } public class ShareResource{ public static void main(String[] args) { TicketTask task new TicketTask(); // 3个线程共用同一个任务对象共享ticket变量 new Thread(task,窗口1).start(); new Thread(task,窗口2).start(); new Thread(task,窗口3).start(); } }3. 任务与线程解耦程度不同继承 Thread线程对象和任务代码耦合在一起线程和任务绑定一个线程对应一套任务。实现 Runnable把 ** 任务Runnable和执行载体Thread 线程** 分离开任务可以被任意多个线程复用代码解耦更好。4. 代码复用性继承 Thread线程类只能作为线程运行复用性弱。实现 RunnableRunnable 只是普通任务类既可以交给 Thread 执行也可以交给线程池执行通用性更强。三、总结优缺点表格对比项继承 Thread 子类实现 Runnable 接口继承限制受 Java 单继承约束不能再继承其他类无继承限制可同时继承父类 实现多个接口资源共享多个线程无法直接共享任务数据多线程可以共享同一个 Runnable 任务资源代码耦合线程与任务强耦合任务和线程解耦职责分离适用场景简单独立的一次性线程任务多线程资源共享、线程池、业务解耦场景开发建议日常项目开发中优先使用实现 Runnable 接口的方式创建线程规避单继承缺陷同时更好地实现多线程数据共享只有简单的独立线程任务才偶尔使用继承 Thread 的写法。四、拓展底层原理两种方式最终都是调用start()来启动线程由 JVM 自动调用run()方法。继承 Thread重写的是 Thread 自身的run()传入 RunnableThread 内部会执行传入 Runnable 对象的run()方法。一句话总结继承 Thread 是把线程和任务写在一起实现 Runnable 是把任务抽离出来让线程去执行这个任务。