线程的生命周期介绍
1. Thread.State 六种状态分别表示什么
Java 线程的生命周期状态由 java.lang.Thread.State 定义,常见面试要点是:Java 的 RUNNABLE 不等于“正在跑”,它包含就绪与运行中(是否真的占用 CPU 由 OS 调度决定)。
NEW:创建了Thread对象,但未调用start()。RUNNABLE:可运行态(就绪或运行中),等待 OS 调度或正在执行。BLOCKED:在进入synchronized临界区时,等待获取监视器锁(Monitor)。WAITING:无限期等待(没有超时),常见于Object.wait()、Thread.join()、LockSupport.park()。TIMED_WAITING:有期限等待,常见于Thread.sleep()、Object.wait(timeout)、Thread.join(timeout)、LockSupport.parkNanos()。TERMINATED:线程执行结束(run()返回或抛出未捕获异常)。
2. 典型状态流转(按触发动作组织)
2.1 NEW -> RUNNABLE -> TERMINATED
start():NEW -> RUNNABLE(开始参与调度)。run()方法执行结束:进入TERMINATED。
2.2 RUNNABLE <-> BLOCKED:与 synchronized 相关
当线程尝试进入 synchronized (lock):
- 拿不到锁:进入
BLOCKED。 - 拿到锁:回到
RUNNABLE(继续执行)。
2.3 RUNNABLE <-> WAITING/TIMED_WAITING:等待/唤醒相关
典型触发点:
Object.wait():进入WAITING,并且释放当前对象监视器锁。Thread.sleep():进入TIMED_WAITING,不会释放锁。LockSupport.park():进入WAITING(更底层的挂起机制)。notify/notifyAll、unpark、超时到期、被中断:可能唤醒回到RUNNABLE。
3. BLOCKED 与 WAITING 的区别(高频易混)
BLOCKED:只和进入synchronized获取 Monitor有关。WAITING/TIMED_WAITING:通常是主动等待(wait/join/park/sleep),并不表示在竞争 Monitor。
4. 最小可复现示例:三种常见等待状态
public class ThreadStateDemo {
private static final Object LOCK = new Object();
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
synchronized (LOCK) {
try {
LOCK.wait(); // WAITING,并释放 LOCK
} catch (InterruptedException ignored) {}
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (LOCK) {
// 持有 LOCK,其他线程进来会 BLOCKED
try { Thread.sleep(10_000); } catch (InterruptedException ignored) {}
}
}, "t2");
t1.start();
Thread.sleep(200);
t2.start();
}
}