1. 继承 Thread 类

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程运行中:" + Thread.currentThread().getName());
}
}

public class Demo {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start(); // 启动线程
}
}

特点:每个线程对象独立,run() 方法写在子类中,使用 start() 启动。

2. 实现 Runnable 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程运行中:" + Thread.currentThread().getName());
}
}

public class Demo {
public static void main(String[] args) {
MyRunnable task = new MyRunnable();
Thread t1 = new Thread(task);
t1.start();
}
}

特点:任务与线程分离,Runnable 只定义任务,Thread 负责调度。

3. 核心区别

对比维度 继承 Thread 实现 Runnable
类的关系 必须是 Thread 子类,单继承限制 实现接口,可同时继承其他类
资源共享 每个线程独立对象,资源不共享 一个 Runnable 实例可被多个 Thread 共享
线程与任务耦合 线程和任务绑定在一起 任务与线程解耦,更灵活
代码复用 run() 方法不可复用 Runnable 可被多个线程复用

4. 资源共享示例对比

4.1 继承 Thread(资源不共享)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class TicketThread extends Thread {
private int tickets = 5;
@Override
public void run() {
while (tickets > 0) {
System.out.println(getName() + " 卖出第 " + tickets-- + " 张票");
}
}
}

// 测试
TicketThread t1 = new TicketThread();
TicketThread t2 = new TicketThread();
t1.start();
t2.start();
// 输出:每个线程各自卖 5 张票,总共 10 张(不符合预期)

4.2 实现 Runnable(资源共享)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class TicketRunnable implements Runnable {
private int tickets = 5;
@Override
public void run() {
while (tickets > 0) {
System.out.println(Thread.currentThread().getName() + " 卖出第 " + tickets-- + " 张票");
}
}
}

// 测试
TicketRunnable task = new TicketRunnable();
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
// 输出:两个线程共享 5 张票,最终卖完 5 张(符合预期)

5. 如何选择?

只需简单线程任务且不涉及资源共享:继承 Thread 写法简单。

需要多个线程共享数据、或类已有父类:必须用 Runnable。

推荐做法:永远优先使用实现 Runnable 接口。它符合面向对象设计原则(组合优于继承),线程池、Lambda 表达式也都是基于 Runnable 的。

从 Java 8 开始,Runnable 作为函数式接口,还可以用 Lambda 简化:

java
new Thread(() -> System.out.println(“Lambda 线程”)).start();

6. 总结

继承 Thread:简单,但单继承限制,资源不易共享。

实现 Runnable:解耦、灵活、可共享资源,配合线程池更强大。

实际开发中,Runnable 是主流选择,继承 Thread 已很少使用。

掌握两种方式的区别,是理解 Java 多线程的第一步。