约 3193 字
Java线程原理、六大状态流转、线程结束判断、安全中断、核心方法区别
本文一次性吃透Java线程底层原理、完整状态流转、线程结束判断、安全中断机制、sleep/wait/join/yield/park全部区别,解决99%线程面试问题,逻辑闭环、无废话、可直接背诵。
一、Java线程底层原理
1. 线程模型(重点)
Java线程采用 一对一内核线程模型(1:1):
- 一个Java线程 = 绑定一条OS内核线程
- 线程的调度、时间片分配、阻塞、唤醒全部由操作系统内核完成
- JVM只负责封装、状态维护、栈内存管理
优缺点:阻塞彻底释放CPU、并发能力强;但线程创建销毁、上下文切换成本高。
2. 线程核心特性
- 线程私有:程序计数器、虚拟机栈、本地方法栈
- 线程共享:堆、方法区
- 线程切换会产生上下文切换开销(保存/恢复现场)
二、Java线程六大状态(JDK Thread.State)
Java 严格定义6种状态,没有 Running 状态,运行中也属于 RUNNABLE。
- NEW:新建线程对象,未调用 start(),无内核线程绑定
- RUNNABLE:可运行/正在运行,等待CPU时间片或正在执行
- BLOCKED:等待获取 synchronized 互斥锁
- WAITING:无限等待,必须手动唤醒(无超时)
- TIMED_WAITING:限时等待,超时自动唤醒
- TERMINATED:线程执行完毕,彻底死亡
三、完整状态流转(面试必背链路)
核心主线:NEW → start() → RUNNABLE → 执行业务代码 → TERMINATED
四大分支阻塞流转:
- RUNNABLE –抢锁失败–> BLOCKED:抢到锁回到RUNNABLE
- RUNNABLE –wait()/join()/park()–> WAITING:notify/notifyAll/unpark 唤醒
- RUNNABLE –sleep()/wait(时间)–> TIMED_WAITING:超时自动唤醒
- 所有阻塞唤醒后,一律回到 RUNNABLE
关键区分(高频坑点)
- BLOCKED:只有 synchronized 锁竞争才会触发
- WAITING/TIMED_WAITING:主动休眠、挂起,释放CPU
四、如何判断线程是否执行完成?(4种方案)
1. isAlive()
true=线程存活(未结束),false=未启动/已结束。
2. getState() == TERMINATED
最精准,直接判断线程终止状态。
3. join() 阻塞等待
主线程阻塞,直到目标线程执行完毕。适合单线程等待。
4. CountDownLatch / CyclicBarrier
多线程场景最优,精准等待一批线程全部执行完成。
五、线程安全中断机制(核心重点)
1. 核心结论:stop() 强制终止 废弃、不安全
stop() 会直接杀死线程、丢失数据、破坏事务一致性,生产绝对禁止使用。
2. Java 安全中断原理(协作式中断)
Java线程中断是 协作式、软中断:
interrupt():只是打一个中断标记,不会立刻终止线程- 线程是否退出,由线程自己判断标记、自主决定
3. 三个中断核心方法
- interrupt():设置中断标志位为true
- isInterrupted():判断是否中断,不清除标志位
- Thread.interrupted():判断是否中断,清除标志位(静态方法)
4. 阻塞线程的中断特性(高频考点)
当线程处于 sleep/wait/join 阻塞状态:
调用 interrupt() → 直接抛出 InterruptedException,并清空中断标志位
5. 标准安全中断写法
while(!Thread.currentThread().isInterrupted()){
// 执行业务逻辑
}
// 收到中断信号,优雅收尾、释放资源、退出线程
6. 为什么要设计成协作式中断?
为了线程安全:让线程可以收尾逻辑、释放锁、释放连接、保证数据一致性,不会被暴力杀死导致数据错乱。
六、线程核心方法原理 & 终极区别(面试必考)
1. sleep() 原理
- 让线程进入 TIMED_WAITING
- 不释放锁(synchronized、lock 都不释放)
- 时间到自动唤醒
- 可被中断抛异常
2. wait() 原理(Object方法)
- 必须在同步代码块中执行
- 进入 WAITING 状态
- 强制释放锁
- 必须 notify/notifyAll 唤醒
3. join() 原理
- 主线程等待子线程执行完毕
- 底层是 wait 实现,会释放锁
- 进入 WAITING/TIMED_WAITING
4. yield() 原理
- 礼让CPU,当前线程主动让出时间片
- 状态不变,仍是 RUNNABLE
- 不释放锁
- 只是降低自己优先级,可能再次抢到CPU
5. park() 原理(LockSupport)
- AQS 底层阻塞工具
- 进入 WAITING 状态
- 不依赖锁、精准唤醒、不会丢失信号
- 支持中断、不抛异常,只返回中断状态
七、方法终极对比表(背诵版)
| 方法 | 是否释放锁 | 状态 | 唤醒方式 |
|---|---|---|---|
| sleep | 不释放 | TIMED_WAITING | 超时/中断 |
| wait | 释放锁 | WAITING | notify |
| join | 释放锁 | WAITING | 线程结束 |
| yield | 不释放 | RUNNABLE | 自动重新竞争 |
| park | 不释放 | WAITING | unpark/中断 |
八、面试一句话终极总结(直接背诵)
- 线程原理:Java线程是1:1内核线程,由OS调度,拥有独立栈空间,共享堆内存。
- 状态流转:六大状态核心区分阻塞类型,锁阻塞是BLOCKED,主动等待是WAITING/TIMED_WAITING。
- 线程结束:可通过状态判断、isAlive、join、CountDownLatch四种方式确认。
- 安全中断:采用协作式中断,interrupt仅打标记,线程自主判断退出,禁止stop暴力终止。
- 方法区别:sleep不释放锁、wait释放锁、yield只是礼让、join等待线程结束、park精准阻塞。