线程怎么创建?Java 四种方式一网打尽
🚀 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 {@Overridepublic void run() {System.out.println("线程执行中:" + Thread.currentThread().getName());}public static void main(String[] args) {new MyThread().start(); // 启动线程}
}
📌 特点:
- 简单粗暴,但不支持多继承,因为 Java 不支持多重继承,不推荐在企业项目中使用。
- 适合学习阶段熟悉线程生命周期。
🧵 方式二:实现 Runnable 接口(推荐)
✅ 代码示例:
public class MyRunnable implements Runnable {@Overridepublic 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> {@Overridepublic 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)。