🚀 Java 中线程的 4 种创建方式详解
创建方式 | 实现方式 | 是否推荐 | 场景说明 |
---|---|---|---|
1. 继承 Thread 类 | class MyThread extends Thread | ❌ 不推荐 | 简单学习、单线程场景 |
2. 实现 Runnable 接口 | class MyRunnable implements Runnable | ✅ 推荐 | 更适合多线程共享资源 |
3. 实现 Callable 接口 | class MyTask implements Callable<T> | ✅ 强烈推荐 | 有返回值的任务、配合线程池使用 |
4. 使用线程池(Executor 框架) | Executors.newFixedThreadPool(...) | ✅ 企业级推荐 | 高并发、大量线程复用 |
🧵 方式一:继承 Thread 类
✅ 代码示例:
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程执行中:" + Thread.currentThread().getName());
}
public static void main(String[] args) {
new MyThread().start(); // 启动线程
}
}
📌 特点:
- 简单粗暴,但不支持多继承,因为 Java 不支持多重继承,不推荐在企业项目中使用。
- 适合学习阶段熟悉线程生命周期。
🧵 方式二:实现 Runnable 接口(推荐)
✅ 代码示例:
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable线程执行:" + Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
}
}
📌 特点:
- 可以避免 Java 的单继承限制。
- 可以实现资源共享(多线程操作同一资源)。
- 更符合面向接口编程思想,因为 Runnable 接口将任务代码和线程控制的代码解耦了,解耦性更强。
🧵 方式三:实现 Callable 接口(带返回值)
✅ 代码示例:
import java.util.concurrent.*;
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "任务结果:" + Thread.currentThread().getName();
}
public static void main(String[] args) throws Exception {
CallableTask task = new CallableTask();
FutureTask<String> futureTask = new FutureTask<>(task);
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
}
}
📌 特点:
- 支持返回结果(通过
Future
获取)。 - 支持抛出异常。
- 面试高频考点,线程池使用必备!
🧵 方式四:使用线程池(企业级推荐)
✅ 代码示例:
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
pool.execute(() -> System.out.println("线程池执行:" + Thread.currentThread().getName()));
}
pool.shutdown();
}
}
📌 特点:
- 控制线程数量,避免资源浪费。
- 提高程序性能,线程复用。
- 实际开发中广泛使用,如 Spring Boot 后台异步任务、微服务间异步通信等。
🎯 面试延伸:常见提问
Q1:Runnable 和 Callable 有什么区别?
- Callable 有返回值,Runnable 没有;
- Callable 可以抛出异常;
- Callable 需要配合
FutureTask
或线程池使用。
Q2:为什么推荐线程池?
- 避免频繁创建销毁线程,提升性能;
- 控制并发数,防止系统崩溃;
- 支持任务调度、延迟执行等高级特性(如 ScheduledExecutorService)。