核心概念
Java线程有6种状态,定义在Thread.State枚举中:
- NEW(新建)
- RUNNABLE(可运行)
- BLOCKED(阻塞)
- WAITING(等待)
- TIMED_WAITING(超时等待)
- TERMINATED(终止)
状态详解与转换
状态转换图
NEW
|
start()
↓
RUNNABLE ←─────────────┐
↙ ↓ ↘ │
BLOCKED WAITING TIMED_WAITING
↘ ↓ ↙ │
RUNNABLE │
↓ │
TERMINATED ──────────────┘
1. NEW(新建)
Thread thread = new Thread(() -> {});
// 此时状态为 NEW
System.out.println(thread.getState()); // NEW
特点:线程对象已创建,但尚未调用start()方法。
2. RUNNABLE(可运行)
thread.start();
// 此时状态为 RUNNABLE
System.out.println(thread.getState()); // RUNNABLE
特点:
- 包含操作系统层面的Running和Ready两种状态
- 线程可能正在执行,也可能在等待CPU时间片
- Java不区分这两种状态,统一为RUNNABLE
进入方式:
NEW→ 调用start()→RUNNABLEBLOCKED/WAITING/TIMED_WAITING→ 条件满足 →RUNNABLE
3. BLOCKED(阻塞)
synchronized(lock) {
// 如果锁被占用,当前线程进入BLOCKED状态
}
特点:等待获取synchronized锁(Monitor)
进入方式:
- 尝试进入
synchronized代码块/方法,但锁被其他线程持有
退出方式:
- 获取到锁 →
RUNNABLE
4. WAITING(无限等待)
// 方式1:Object.wait()
synchronized(lock) {
lock.wait(); // 进入WAITING,释放锁
}
// 方式2:Thread.join()
thread.join(); // 等待thread线程结束
// 方式3:LockSupport.park()
LockSupport.park(); // 进入WAITING
特点:
- 无限期等待,直到被显式唤醒
wait()会释放锁,park()不涉及锁
进入方式:
Object.wait()(无超时参数)Thread.join()(无超时参数)LockSupport.park()
退出方式:
Object.notify()/notifyAll()- 被等待的线程执行完毕
LockSupport.unpark()
5. TIMED_WAITING(超时等待)
// 方式1:Thread.sleep()
Thread.sleep(1000); // 进入TIMED_WAITING,不释放锁
// 方式2:Object.wait(timeout)
synchronized(lock) {
lock.wait(1000); // 进入TIMED_WAITING,释放锁
}
// 方式3:Thread.join(timeout)
thread.join(1000);
// 方式4:LockSupport.parkNanos()/parkUntil()
LockSupport.parkNanos(1000000000L); // 1秒
特点:
- 有超时时间,到期自动唤醒
sleep()不释放锁,wait(timeout)释放锁
退出方式:
- 超时时间到期
- 被提前唤醒(
notify()/unpark())
6. TERMINATED(终止)
// 线程执行完run()方法,或抛出未捕获异常
特点:
- 线程执行结束,生命周期终结
- 不可重新启动(再次调用
start()会抛IllegalThreadStateException)
源码关键点
Thread.State源码
public enum State {
NEW, // 初始状态
RUNNABLE, // 运行状态
BLOCKED, // 阻塞状态(等待锁)
WAITING, // 等待状态(无限期)
TIMED_WAITING, // 超时等待
TERMINATED; // 终止状态
}
状态检查
public State getState() {
// 由JVM实现,返回线程当前状态
return jdk.internal.misc.VM.toThreadState(threadStatus);
}
面试常见陷阱
1. BLOCKED vs WAITING
| 状态 | 触发场景 | 是否释放锁 |
|---|---|---|
| BLOCKED | 等待synchronized锁 | 未持有锁 |
| WAITING | wait()/join()/park() | wait()释放锁 |
2. sleep() vs wait()
// sleep:TIMED_WAITING,不释放锁
synchronized(lock) {
Thread.sleep(1000); // 仍持有lock
}
// wait:WAITING,释放锁
synchronized(lock) {
lock.wait(); // 释放lock,其他线程可进入
}
3. RUNNABLE的双重含义
// RUNNABLE包含两种操作系统状态:
// 1. Ready:在就绪队列,等待CPU调度
// 2. Running:正在CPU上执行
// Java层面无法区分,统一为RUNNABLE
答题总结
面试标准答案:
Java线程有6种状态:
- NEW:创建未启动
- RUNNABLE:可运行(含Running和Ready)
- BLOCKED:等待synchronized锁
- WAITING:无限期等待(wait/join/park)
- TIMED_WAITING:超时等待(sleep/wait(timeout))
- TERMINATED:执行结束
关键流转:
NEW→start()→RUNNABLERUNNABLE→ 等待锁 →BLOCKED→ 获取锁 →RUNNABLERUNNABLE→wait()/park()→WAITING→notify()/unpark()→RUNNABLERUNNABLE→sleep()/wait(timeout)→TIMED_WAITING→ 超时/唤醒 →RUNNABLERUNNABLE→ 执行完毕 →TERMINATED
核心区别:
- BLOCKED是被动等锁,WAITING是主动等待
- sleep()不释放锁,wait()释放锁
- RUNNABLE包含操作系统的就绪和运行两种状态