一、线程生命周期的理论基础
在Java中,线程的生命周期是一个复杂但设计精巧的状态机模型。Java线程的状态在java.lang.Thread.State枚举中明确定义,共包含6种状态:
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
这些状态精确反映了线程在JVM中的实际状态,与操作系统层面的线程状态有所区别但密切相关。
二、各状态详解及底层实现
1. NEW(新建状态)
当线程对象被创建但尚未调用start()方法时处于此状态。
Thread thread = new Thread(() -> {
// 线程任务
});
// 此时thread.getState() == Thread.State.NEW
底层实现:
- 在调用
new Thread()时,JVM会初始化线程对象但不会立即向操作系统申请线程资源 - 此时线程的
threadStatus字段(native实现)为0,表示尚未启动
2. RUNNABLE(可运行状态)
调用start()方法后,线程进入RUNNABLE状态。注意这与传统操作系统中的"运行中"和"就绪"状态不同,Java将它们合并为RUNNABLE。
thread.start();
// 此时thread.getState() == Thread.State.RUNNABLE
底层实现:
start()方法调用本地方法start0(),最终通过pthread_create(Linux)或CreateThread(Windows)创建系统线程- 线程进入就绪队列,等待CPU调度
- 在HotSpot源码中,线程状态由
JavaThread对象的_thread_state字段维护
3. BLOCKED(阻塞状态)
线程在等待获取监视器锁(synchronized)时进入此状态。
synchronized (lock) {
// 另一个线程在此处等待锁时会进入BLOCKED状态
}
底层实现:
- 当线程竞争synchronized锁失败时,会进入
ObjectMonitor的_EntryList队列 - 在HotSpot源码中,通过
ObjectMonitor::enter()和ObjectMonitor::ExitEpilog()方法管理状态转换 - 底层使用pthread_mutex_lock等系统调用实现阻塞
4. WAITING(无限期等待状态)
当线程调用以下方法时会进入WAITING状态:
Object.wait()Thread.join()LockSupport.park()
synchronized (lock) {
lock.wait(); // 进入WAITING状态
}
底层实现:
wait()方法会将线程放入ObjectMonitor的_WaitSet队列- 在HotSpot中,通过
ObjectMonitor::wait()方法实现,最终可能调用pthread_cond_wait - 需要其他线程调用
notify()/notifyAll()才能唤醒
5. TIMED_WAITING(限期等待状态)
与WAITING类似,但带有超时时间:
Thread.sleep(long)Object.wait(long)Thread.join(long)LockSupport.parkNanos()LockSupport.parkUntil()
Thread.sleep(1000); // 进入TIMED_WAITING状态
底层实现:
- 在HotSpot中,通过
os::sleep()或pthread_cond_timedwait实现定时等待 - JVM维护一个定时器队列来管理这些线程
6. TERMINATED(终止状态)
线程执行完毕或异常退出后进入此状态。
thread.start();
thread.join();
// 线程结束后,thread.getState() == Thread.State.TERMINATED
底层实现:
- 线程执行完
run()方法后,会调用Thread::exit()方法 - 最终通过
JavaThread::thread_main_inner()清理线程资源 - 但Thread对象仍然存在,可以被查询状态
三、状态转换图及关键方法
NEW
↓ start()
RUNNABLE ←———┐
| ↓ |
| 阻塞获取锁 → BLOCKED
| ↓ wait()/join()/park()
| WAITING ←┐
| ↓ 带超时的等待 | notify()/notifyAll()/unpark()
| TIMED_WAITING
↓
TERMINATED
关键方法对状态的影响:
start(): NEW → RUNNABLEyield(): RUNNABLE → RUNNABLE(提示调度器让出CPU)synchronized: RUNNABLE ↔ BLOCKEDwait(): RUNNABLE → WAITING (需先获取锁)notify(): WAITING → BLOCKED (需重新获取锁)sleep(): RUNNABLE → TIMED_WAITING
四、JVM底层实现细节
在HotSpot虚拟机中,线程状态管理涉及以下关键组件:
- JavaThread类:表示一个Java线程,包含
_thread_state字段 - ObjectMonitor类:实现synchronized和wait/notify机制
- ParkEvent类:实现
LockSupport.park()/unpark()
状态转换的核心代码片段(简化):
// HotSpot源码中的状态转换示例
void ObjectMonitor::wait(long millis, bool interruptible, TRAPS) {
// 将线程加入WaitSet
AddWaiter(&node);
// 释放锁
exit(true, Self);
// 等待被唤醒或超时
while (!is_on_condition_variable()) {
if (millis <= 0) {
Self->_ParkEvent->park();
} else {
Self->_ParkEvent->park(millis);
}
}
// 重新竞争锁
enter(THREAD);
}
五、诊断线程状态的实际应用
- jstack分析:通过线程转储查看各线程状态
- VisualVM/JConsole:图形化查看线程状态
- 编程获取状态:
thread.getState()
示例诊断代码:
Thread thread = new Thread(() -> {
try {
synchronized (lock) {
lock.wait(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("After creation: " + thread.getState()); // NEW
thread.start();
System.out.println("After start: " + thread.getState()); // RUNNABLE
Thread.sleep(100);
synchronized (lock) {
System.out.println("After wait: " + thread.getState()); // TIMED_WAITING
}
thread.join();
System.out.println("After finish: " + thread.getState()); // TERMINATED
六、总结
Java线程生命周期模型是对操作系统线程状态的抽象和扩展,既考虑了跨平台性又提供了精确的状态控制。理解这些状态及其转换关系对于以下场景尤为重要:
- 多线程程序调试
- 死锁/活锁问题诊断
- 线程池调优
- 并发控制设计
104

被折叠的 条评论
为什么被折叠?



