1. 多线程核心原理与面试要点解析
1.1 线程与进程的本质区别
在操作系统层面,进程是资源分配的基本单位,而线程是CPU调度的基本单位。举个生活中的例子:如果把浏览器看作一个进程,那么它的每个标签页就是一个线程。它们共享浏览器的地址空间(内存资源),但各自独立执行网页渲染任务。
关键差异点:
- 资源占用:进程拥有独立的地址空间,线程共享进程资源
- 创建开销:线程创建比进程快10-100倍(Linux下约10μs vs 1ms)
- 通信成本:进程间通信(IPC)需要内核介入,线程可直接读写共享内存
- 容错性:单个线程崩溃会导致整个进程终止
注意:在Java中直接操作线程属于较底层的做法,实际开发更推荐使用线程池管理
1.2 线程创建的三种方式深度剖析
1.2.1 继承Thread类
java复制class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread ID: " + Thread.currentThread().getId());
}
}
// 使用示例
new MyThread().start();
特点:
- 简单直接,但Java单继承特性限制了扩展性
- 线程与任务强耦合,不符合单一职责原则
1.2.2 实现Runnable接口
java复制class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Running in thread: " + Thread.currentThread().getName());
}
}
// 使用示例
new Thread(new MyRunnable()).start();
优势:
- 任务与执行解耦
- 可复用同一个Runnable对象
- 方便配合线程池使用
1.2.3 实现Callable接口
java复制class PrimeCalculator implements Callable<List<Integer>> {
private final int max;
public PrimeCalculator(int max) {
this.max = max;
}
@Override
public List<Integer> call() {
// 计算质数的实现...
return primes;
}
}
// 使用示例
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<List<Integer>> future = executor.submit(new PrimeCalculator(100));
List<Integer> result = future.get(); // 阻塞获取结果
核心价值:
- 支持返回值(Future模式)
- 允许抛出检查异常
- 配合ExecutorService实现更复杂的异步编程
性能对比:
| 创建方式 | 内存开销 | 创建速度 | 适用场景 |
|---|---|---|---|
| 继承Thread | 较高 | 慢 | 简单测试场景 |
| 实现Runnable | 低 | 快 | 大多数业务场景 |
| 实现Callable | 中等 | 中等 | 需要返回值的任务 |
1.3 线程状态机与生命周期
1.3.1 五种状态详解
-
NEW(新建):
- 刚创建未调用start()
- 线程栈大小默认1MB(可通过-Xss参数调整)
-
RUNNABLE(可运行):
- 包括就绪和运行中两种子状态
- 受线程调度器控制,非确定性切换
-
BLOCKED(阻塞):
- 等待监视器锁(synchronized)
- 不会消耗CPU周期
-
WAITING(等待):
- 无限期等待,需外部唤醒
- 通过Object.wait()或Thread.join()进入
-
TERMINATED(终止):
- run()执行完毕或抛出未捕获异常
- 线程对象可能仍在堆中,但线程已销毁
1.3.2 状态转换触发条件
mermaid复制stateDiagram-v2
[*] --> NEW
NEW --> RUNNABLE: start()
RUNNABLE --> BLOCKED: 等待锁
BLOCKED --> RUNNABLE: 获取锁
RUNNABLE --> WAITING: wait()/join()
WAITING --> RUNNABLE: notify()/线程结束
RUNNABLE --> TERMINATED: run()结束
实测技巧:jstack命令可以抓取线程快照,分析真实应用中的线程状态分布
1.4 线程同步与锁机制
1.4.1 synchronized的底层实现
- 对象头Mark Word:存储锁状态(无锁、偏向锁、轻量级锁、重量级锁)
