Java线程原理、六大状态流转、线程结束判断、安全中断、核心方法区别

约 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。

  1. NEW:新建线程对象,未调用 start(),无内核线程绑定
  2. RUNNABLE:可运行/正在运行,等待CPU时间片或正在执行
  3. BLOCKED:等待获取 synchronized 互斥锁
  4. WAITING:无限等待,必须手动唤醒(无超时)
  5. TIMED_WAITING:限时等待,超时自动唤醒
  6. 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释放锁WAITINGnotify
join释放锁WAITING线程结束
yield不释放RUNNABLE自动重新竞争
park不释放WAITINGunpark/中断

八、面试一句话终极总结(直接背诵)

  • 线程原理:Java线程是1:1内核线程,由OS调度,拥有独立栈空间,共享堆内存。
  • 状态流转:六大状态核心区分阻塞类型,锁阻塞是BLOCKED,主动等待是WAITING/TIMED_WAITING。
  • 线程结束:可通过状态判断、isAlive、join、CountDownLatch四种方式确认。
  • 安全中断:采用协作式中断,interrupt仅打标记,线程自主判断退出,禁止stop暴力终止。
  • 方法区别:sleep不释放锁、wait释放锁、yield只是礼让、join等待线程结束、park精准阻塞。