Java线程生命周期详解
导语:
Java 并发编程是后端面试中的重头戏,而“线程生命周期与状态”更是高频面试题之一。别以为这只是背背图的题型,真正能打动面试官的回答,往往要结合源码、实际应用与底层原理。本文将带你从面试官视角拆解这道经典问题,掌握得当,它将是你的“加分利器”。
一、面试主题概述
Java 线程模型是构建并发程序的基础。无论是阿里、字节、腾讯,还是各大中厂,都非常重视候选人对 线程状态变化与调度机制的理解。原因很简单——理解线程生命周期不仅能写出正确的并发代码,还能帮助你排查线程死锁、性能卡顿、资源争用等问题。
因此,“说说线程的生命周期和状态”这道题虽看似基础,实则考察的深度不容小觑。
二、高频面试题汇总
- Java 中线程有哪些状态?它们的含义是什么?
- 线程从一个状态转移到另一个状态的条件是什么?
- NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED 的区别?
wait()
和sleep()
会改变线程状态吗?有何不同?- 在项目中有没有遇到过线程卡死、状态异常的情况?是怎么排查的?
三、重点题目详解
题目1:Java 中线程的生命周期有哪些状态?分别代表什么含义?
这是基础题,也是后面所有并发题的基础。大多数候选人都能背出几个状态,但真正理解状态间切换的却不多。
✅ 解答要点:
Java 中线程生命周期共分为 6 个状态,它们对应 java.lang.Thread.State
枚举:
public enum Thread.State {NEW, // 新建状态,还未 start()RUNNABLE, // 就绪/运行状态(OS 层未必已运行)BLOCKED, // 被 synchronized 锁阻塞WAITING, // 无限期等待,如 wait()TIMED_WAITING, // 有时限的等待,如 sleep(), join(timeout)TERMINATED // 线程已结束,run() 执行完或异常退出
}
✅ 示例代码:
public class ThreadStateDemo {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {try {Thread.sleep(1000); // TIMED_WAITING} catch (InterruptedException e) {e.printStackTrace();}});System.out.println(thread.getState()); // NEWthread.start();System.out.println(thread.getState()); // RUNNABLEThread.sleep(100);System.out.println(thread.getState()); // TIMED_WAITINGthread.join();System.out.println(thread.getState()); // TERMINATED}
}
✅ 面试官考察点:
- 是否理解状态与方法的对应关系;
- 是否知道
RUNNABLE
包括 “正在运行” 和 “就绪队列等待”; - 能否解释
BLOCKED
与WAITING
的本质区别(是否等待锁 vs 线程协作机制);
题目2:说说 BLOCKED 和 WAITING 的区别?
这是一道经典追问题,用于判断候选人是否真的理解线程调度。
✅ 解答思路:
-
BLOCKED(阻塞):线程正在等待一个 synchronized锁。例如两个线程争抢一个对象锁,后来的线程会进入 BLOCKED 状态。
-
WAITING(等待):线程主动调用
Object.wait()
或Thread.join()
等,进入等待队列,等待其他线程的唤醒(如notify()
、join
完成)。
状态 | 典型触发方法 | 唤醒方式 |
---|---|---|
BLOCKED | synchronized | 获得锁 |
WAITING | wait(), join() | notify(), join 结束 |
✅ 代码示例:
public class BlockedWaitingDemo {private static final Object LOCK = new Object();public static void main(String[] args) {// BLOCKED 示例Thread t1 = new Thread(() -> {synchronized (LOCK) {while (true) {} // 占着锁不放}});Thread t2 = new Thread(() -> {synchronized (LOCK) {System.out.println("拿到锁"); // 永远执行不到}});t1.start();Thread.sleep(100);t2.start();Thread.sleep(100);System.out.println(t2.getState()); // BLOCKED}
}
题目3:sleep() 和 wait() 的区别是?是否会释放锁?
这道题最容易答错。很多候选人混淆了这两个方法的语义和行为。
✅ 解答核心:
方法 | 属于类 | 是否释放锁 | 是否可被唤醒 |
---|---|---|---|
sleep() | Thread | 否 | 否 |
wait() | Object | 是 | 是(notify) |
sleep()
是让线程 进入 TIMED_WAITING,时间到后自动回到 RUNNABLE;wait()
是让线程进入 WAITING 状态,并释放对象锁,需notify()
或notifyAll()
唤醒。
✅ 示例片段:
synchronized (LOCK) {LOCK.wait(); // 释放锁Thread.sleep(1000); // 不释放锁
}
四、面试官视角与加分项
🎯 面试官为啥爱问线程状态?
- 线程状态是并发调度的底层逻辑;
- 异常线程行为(死锁、卡顿)都源自状态切换异常;
- 候选人是否能用状态图还原运行现场,体现其并发思维模型成熟度;
🌟 如何答出亮点?
- 不要只背状态名,要画出状态迁移图;
- 举例真实遇到的问题,如“线程池中发现一直卡在 BLOCKED 是因为锁未释放”;
- 引用源码或 JVM 实现层内容(如 OS thread 的 Runnable 并不等于真正执行)。
五、总结与建议
Java 线程生命周期表面上是六个状态,背后蕴含的是整个 JVM 并发模型的设计思想。掌握线程状态及切换逻辑,不仅有助于通过面试,更是编写高性能、高可控并发程序的前提。
✅ 建议你在准备时:
- 熟练背诵 + 理解
Thread.State
各状态; - 结合
synchronized
,wait/notify
,sleep
,join
编写小 Demo 验证状态变化; - 在项目中主动使用
thread.getState()
来调试并发问题,养成实战习惯。