[硬核对比] 进程 vs 线程 vs Java线程:状态模型的“套娃”游戏
[硬核对比] 进程 vs 线程 vs Java线程:状态模型的“套娃”游戏
作者: YUNGUI
标签: #操作系统 #Java #多线程 #面试必问
引言
在面试中,我们经常会被问到“线程的状态”。
这时候,如果你的回答是“就绪、运行、阻塞...”,面试官可能会追问:“那 Java 里的 TIMED_WAITING 是什么?”
如果你回答是“New, Runnable, Blocked...”,面试官又可能会问:“那 CPU 正在执行的时候,线程处于什么状态?”
很多人晕就晕在,操作系统理论的状态模型和编程语言(Java)实现的 API 模型并不完全是一回事。
今天我们就把这三个概念:进程状态、OS 线程状态、Java 线程状态,放在一起做一个彻底的对比和映射。
第一层:操作系统的经典视角 (进程/线程通用)
在操作系统原理课本中,无论是进程还是线程,为了管理它们的生命周期,都遵循经典的 “五态模型”。
这是最底层的逻辑,描述了 CPU 调度和资源等待的基本规则。
- 新建 (New):创建中,资源(PCB/TCB)还没分配好。
- 就绪 (Ready):万事俱备,只欠 CPU。在就绪队列排队,一旦抢到时间片就能跑。
- 运行 (Running):正在 CPU 上狂奔。
- 阻塞 (Blocked):被迫停下来。等待磁盘 I/O、网卡数据或锁。注意:此时给它 CPU 它也干不了活。
- 终止 (Terminated):任务结束,资源回收。
📊 经典五态流转图
进程 vs 线程的区别:
虽然状态名字一样,但进程切换涉及内存页表切换,开销巨大;线程切换只涉及寄存器上下文,开销很小。现代 OS 调度的是线程,进程只是资源的容器。
第二层:Java 语言的独特视角 (The JVM Way)
当你打开 JDK 源码查看 Thread.State 枚举时,你会发现它定义了 6 种状态,而且跟操作系统的 5 种状态对不上号。
public enum State {NEW,RUNNABLE, // 重点!BLOCKED, // 锁阻塞WAITING, // 无限等待TIMED_WAITING, // 超时等待TERMINATED;
}
为什么 Java 要搞特殊?我们来看看这 6 种状态的具体含义。
1. NEW (新建)
线程对象被创建(new Thread()),但还没有调用 start() 方法。此时它只是堆内存里的一个普通对象。
2. RUNNABLE (可运行) —— 最大的误区!
这是 Java 最独特的设计。Java 的 RUNNABLE 状态,实际上涵盖了操作系统的【就绪 Ready】和【运行 Running】两个状态。
- 为什么合并?
因为在现代分时操作系统中,CPU 的时间片切换非常快(毫秒级)。一个线程在“运行”和“就绪”之间反复横跳,JVM 如果要实时去追踪这个微小的状态变化,开销太大且没有意义。 - 结论:只要线程愿意干活(没被阻塞),不管它现在是正在干活(Running),还是在排队等活(Ready),在 Java 眼里它都是
RUNNABLE。
3. BLOCKED (阻塞)
这里的阻塞是非常狭义的。只有一种情况会让 Java 线程进入 BLOCKED:
- 等待
synchronized锁(Monitor Lock)。 - 注意:调用
Lock接口(JUC)等待,并不属于 BLOCKED,而是 WAITING。
4. WAITING (无限等待)
表示线程在等待另一个线程执行特定动作。需要被手动唤醒(notify)。
- 常见场景:
Object.wait()、Thread.join()、LockSupport.park()。
5. TIMED_WAITING (超时等待)
和 WAITING 类似,但它有个闹钟,时间到了自己会醒。
- 常见场景:
Thread.sleep(1000)、Object.wait(1000)。
6. TERMINATED (终止)
线程的 run() 方法执行结束。
第三层:上帝视角——OS 与 Java 的状态映射
现在,我们把操作系统的 5 态和 Java 的 6 态拼在一起,就能看清真相了。
🧩 状态映射关系表
| 操作系统状态 (OS) | Java 线程状态 (JVM) | 说明 |
|---|---|---|
| New (新建) | NEW | 没啥区别,都是刚生出来。 |
| Ready (就绪) | RUNNABLE | Java 不区分你是正在跑还是在排队, 统称“能跑 (Runnable)”。 |
| Running (运行) | RUNNABLE | 同上。 |
| Blocked (阻塞) | BLOCKED | 特指等待 synchronized 隐式锁。 |
| Blocked (阻塞) | WAITING | 等待 notify 或显式锁 ReentrantLock。 |
| Blocked (阻塞) | TIMED_WAITING | 等待 sleep 或超时唤醒。 |
| Terminated (结束) | TERMINATED | 任务结束。 |
⚠️ 一个有趣的特例:I/O 阻塞去哪了?
当 Java 线程进行网络 I/O 或磁盘 I/O(比如读大文件)时,在操作系统层面,线程通过系统调用进入了内核态,此时它是 阻塞 (Blocked) 的,因为要等硬盘转圈圈。
但在 Java 层面,该线程的状态依然是 RUNNABLE!
- 原因:Java 认为 I/O 阻塞是操作系统的事,JVM 并不关心(或者说它认为这只是代码执行过程中的一段耗时操作)。只有涉及到 Java 层面的锁竞争或显式等待,JVM 才会标记为阻塞/等待。
终极图解:Java 线程生命周期全景
总结
- 五种状态是操作系统教科书的标准,用来描述所有进程/线程的底层行为。
- 六种状态是 Java API 的定义,它是为了配合 Java 语言特性(如 synchronized、wait/notify)而设计的抽象。
- 最大的坑:Java 没有
Running状态,它把Running和Ready打包成了RUNNABLE。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/991970.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!