当前位置: 首页 > news >正文

Thread线程状态

线程的状态及状态转换全解析

Java 线程的状态是并发编程的基础,JDK 官方(java.lang.Thread.State 枚举)定义了6种核心状态,状态转换则围绕“线程生命周期”和“同步/阻塞操作”展开。下面从「状态定义→转换规则→实战示例」讲透这一核心知识点。

一、先明确:Java 线程的 6 种核心状态

Thread.State 枚举明确了线程的所有合法状态,每个状态对应线程生命周期的一个阶段,先看官方定义:

状态名称 核心含义
NEW(新建) 线程对象已创建,但未调用 start() 方法,未真正启动
RUNNABLE(可运行) 线程调用 start() 后进入该状态(包含「正在运行」和「等待CPU调度」两种子状态)
BLOCKED(阻塞) 线程因竞争对象锁(如 synchronized)被阻塞,等待获取锁
WAITING(等待) 线程无时限等待(需其他线程显式唤醒),如 Object.wait()Thread.join()
TIMED_WAITING(计时等待) 线程有时间限制的等待,如 Thread.sleep(ms)Object.wait(ms)
TERMINATED(终止) 线程执行完成(run() 方法结束)或异常终止,生命周期结束

注意:很多人会混淆「RUNNABLE 的子状态」—— RUNNABLE 包含“就绪(等待CPU)”和“运行(占用CPU)”,但 JDK 并未将其拆分为两个独立状态,统一归为 RUNNABLE。

二、核心:线程状态转换规则(附流程图)

线程的状态转换是“单向为主、部分双向”的,核心流转逻辑如下(用 Mermaid 可视化):

graph TDA[NEW 新建] -->|调用start()| B[RUNNABLE 可运行]B -->|竞争synchronized锁失败| C[BLOCKED 阻塞]C -->|获取到synchronized锁| BB -->|调用Object.wait()/Thread.join()| D[WAITING 等待]B -->|调用Thread.sleep(ms)/Object.wait(ms)| E[TIMED_WAITING 计时等待]D -->|其他线程调用Object.notify()/notifyAll()| BE -->|超时自动唤醒 或 其他线程notify()| BD -->|被中断(interrupt())| BE -->|被中断(interrupt())| BB -->|run()执行完成/异常终止| F[TERMINATED 终止]D -->|被中断| BE -->|被中断| B

逐类拆解关键转换场景

1. NEW → RUNNABLE:唯一触发方式

只有调用线程的 start() 方法,才能让线程从“新建”进入“可运行”状态,且一个线程只能调用一次 start()(多次调用会抛出 IllegalThreadStateException)。

示例:

// NEW 状态:仅创建对象,未启动
Thread t = new Thread(() -> System.out.println("线程运行"));
System.out.println(t.getState()); // 输出:NEW// 调用start(),进入RUNNABLE
t.start();
System.out.println(t.getState()); // 大概率输出:RUNNABLE(CPU调度可能有延迟)

2. RUNNABLE ↔ BLOCKED:仅与 synchronized 锁相关

只有竞争 synchronized 修饰的方法/代码块失败时,线程才会进入 BLOCKED 状态;一旦获取到锁,立即回到 RUNNABLE。

注意:Lock 锁(如 ReentrantLock)的等待不会进入 BLOCKED 状态,而是进入 WAITING/TIMED_WAITING(因为 Lock 基于 Condition 实现,底层调用 LockSupport.park())。

示例:

// 定义一个锁对象
Object lock = new Object();// 线程1:先获取锁,持有5秒
Thread t1 = new Thread(() -> {synchronized (lock) {try {Thread.sleep(5000); // 持有锁期间sleep,状态为TIMED_WAITING} catch (InterruptedException e) {e.printStackTrace();}}
});// 线程2:竞争锁失败,进入BLOCKED状态
Thread t2 = new Thread(() -> {synchronized (lock) {System.out.println("t2获取到锁");}
});t1.start();
Thread.sleep(100); // 确保t1先获取锁
t2.start();
Thread.sleep(100);
System.out.println(t1.getState()); // TIMED_WAITING(持有锁sleep)
System.out.println(t2.getState()); // BLOCKED(等待锁)

3. RUNNABLE → WAITING:无时限等待(需手动唤醒)

触发场景(核心3个):

  • 调用 Object.wait()(需先持有对象锁,释放锁后进入等待);
  • 调用 Thread.join()(无参版,等待目标线程终止);
  • 调用 LockSupport.park()(无参版,底层支撑 Lock 锁)。

唤醒方式:

  • Object.wait() → 其他线程调用 Object.notify()/notifyAll()(需持有同一把锁);
  • Thread.join() → 目标线程执行完成;
  • LockSupport.park() → 其他线程调用 LockSupport.unpark(线程对象)

示例(wait/notify):

Object lock = new Object();
Thread t = new Thread(() -> {synchronized (lock) {try {System.out.println("进入WAITING状态");lock.wait(); // 释放锁,进入WAITINGSystem.out.println("被唤醒,回到RUNNABLE");} catch (InterruptedException e) {e.printStackTrace();}}
});t.start();
Thread.sleep(100);
System.out.println(t.getState()); // WAITING// 主线程唤醒t
synchronized (lock) {lock.notify();
}

4. RUNNABLE → TIMED_WAITING:有时限等待

触发场景(核心5个):

  • Thread.sleep(long ms)(最常用,不释放锁);
  • Object.wait(long ms)(释放锁,超时自动唤醒);
  • Thread.join(long ms)(超时自动退出等待);
  • LockSupport.parkNanos(long ns)
  • LockSupport.parkUntil(long deadline)

唤醒方式:

  • 超时自动唤醒(回到 RUNNABLE);
  • 未超时被其他线程唤醒(如 notify()/unpark());
  • 被中断(interrupt()),抛出 InterruptedException 并回到 RUNNABLE。

示例(sleep 进入 TIMED_WAITING):

Thread t = new Thread(() -> {try {Thread.sleep(3000); // 进入TIMED_WAITING} catch (InterruptedException e) {e.printStackTrace();}
});
t.start();
Thread.sleep(100);
System.out.println(t.getState()); // TIMED_WAITING

5. 所有可运行状态 → TERMINATED:线程终止

线程进入 TERMINATED 的唯一原因:

  • run() 方法正常执行完毕;
  • 运行过程中抛出未捕获的异常(如 NullPointerException),导致线程终止。

示例:

Thread t = new Thread(() -> {System.out.println("线程执行中");
});
t.start();
Thread.sleep(1000); // 等待线程执行完成
System.out.println(t.getState()); // TERMINATED

三、易混淆点澄清

  1. BLOCKED vs WAITING/TIMED_WAITING
    • BLOCKED 仅针对 synchronized 锁竞争;
    • WAITING/TIMED_WAITING 是主动调用等待方法(如 wait()/sleep())导致的等待。
  2. sleep() 不释放锁,wait() 释放锁
    • Thread.sleep() 只是让线程暂停执行,不会释放已持有的 synchronized 锁;
    • Object.wait() 会立即释放持有的对象锁,等待被唤醒后需重新竞争锁。
  3. 中断对状态的影响
    • 对 WAITING/TIMED_WAITING 状态的线程调用 interrupt(),会抛出 InterruptedException,并让线程回到 RUNNABLE 状态;
    • 中断不会直接终止线程,只是设置中断标志位,线程需自行检测并处理。

总结

  1. 核心状态:Java 线程有 NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED 6 种状态,由 Thread.State 枚举定义;
  2. 核心转换
    • NEW 只能通过 start() 进入 RUNNABLE;
    • RUNNABLE 因锁竞争进入 BLOCKED,获取锁后返回;
    • RUNNABLE 因无时限/有时限等待进入 WAITING/TIMED_WAITING,唤醒/超时后返回;
    • 所有可运行状态最终都会因执行完成/异常进入 TERMINATED;
  3. 关键区别:BLOCKED 仅与 synchronized 锁相关,sleep() 不释放锁,wait() 释放锁。
http://www.jsqmd.com/news/444541/

相关文章:

  • 苹果音乐推出AI歌曲和视觉内容可选标识标签
  • Vibe Coding的致命隐患:你必须知道的技术债务和扩展性危机
  • 中草药检测数据集(10000 张图片已划分、已标注)| AI训练适用于目标检测任务
  • 浊流
  • ElasticSearch 常见高频面试题
  • 听歌会员的告别!R3PLAY 极简播放器 + cpolar,外网也能听遍全网歌
  • happiness and sadness
  • 炸裂新招!响应式提示系统设计模式革新提示工程架构师工作流程
  • easyRE1
  • 周赛 Round 51
  • 2024最新:AI原生应用中知识抽取的10大最佳实践
  • 具身智能构建统一跨模态表示空间的优秀的方法
  • 完整教程:【Mybatis】动态SQL与留言板小项目
  • ClickHouse与ArangoDB对比:多模型数据库选择
  • 蓝桥15/B/5/拔河
  • 寻找Confluence替代软件?2026年五大专业工具全面对比评测 - 资讯焦点
  • 2026专业研发管理软件靠谱榜单-国产替代首选竟是它 - 资讯焦点
  • 2026年,北京茅台酒回收找哪家?新手不踩坑,老牌商家更靠谱 - 宁夏壹山网络
  • 2026成都写字楼出租/租赁中介优质推荐榜 资质服务双优之选 - 资讯焦点
  • 如何把 Git 分支上的特定提交移动到另一个分支
  • Java实战:高效实现Word与TXT文档互转的完整指南
  • 2026年专属健康管家服务平台推荐:谁是真正“靠谱”的高端健康管理伙伴? - 资讯焦点
  • 2026年五款常用需求管理工具哪个功能全面?企业选型参考 - 资讯焦点
  • python sys.set_int_max_str_digits(BIT)
  • 解决SCI语言难题!2026英文润色机构测评,艾德思综合实力位居第一 - 资讯焦点
  • Elasticsearch 进阶玩法
  • 优化大数据领域数据架构,释放数据潜力
  • 未来十二个月:2026年将改变AI进程的十件事
  • interrupted、interrupt、isInterrupted 三者关系全解析
  • 20260306紫题训练总结 - Link