Home 并发编程:Java 线程生命周期
Post
Cancel

并发编程:Java 线程生命周期

Java 线程生命周期

在这里插入图片描述


各状态解释与转换触发条件

状态 含义 转换触发条件
NEW(新建) 创建了线程对象,但未调用 start() 调用 start() 进入 Runnable
RUNNABLE(可运行) 已启动线程,正在等待 CPU 调度(可能已运行) 被操作系统调度执行代码时进入 Running
RUNNING(运行) 实际占用 CPU 执行线程代码(属于 RUNNABLE 的子集) <ul><li>执行 wait() 进入 WAITING</li><li>执行 sleep()join()LockSupport.parkNanos() 等进入 TIMED_WAITING</li><li>竞争锁失败进入 BLOCKED</li><li>执行完毕进入 TERMINATED</li></ul>
BLOCKED(阻塞) 等待获取某个 monitor 锁(即 synchronized 获得锁后返回 RUNNABLE
WAITING(等待) 无限期等待被其他线程唤醒(如 Object.wait()Thread.join()LockSupport.park() notify()notifyAll()join() 线程结束唤醒进入 RUNNABLE
TIMED_WAITING(超时等待) 在指定时间内等待,如 sleep(ms)wait(ms)join(ms)parkNanos() 超时时间到或被唤醒后进入 RUNNABLE
TERMINATED(终止) 线程执行完 run() 方法,或异常退出 线程生命周期结束,不可再运行

状态转换总结

触发事件 状态变迁
start() 被调用 NEW → RUNNABLE
获得 CPU 执行时间片 RUNNABLE → RUNNING
执行 wait() RUNNING → WAITING
执行 sleep()join(ms) RUNNING → TIMED_WAITING
等待锁资源 RUNNING → BLOCKED
notify() 唤醒 WAITING → RUNNABLE
超时等待结束 TIMED_WAITING → RUNNABLE
获取到锁 BLOCKED → RUNNABLE
run() 方法执行完毕 任意状态 → TERMINATED

当然,以下是对比 sleep()wait()notify()notifyAll() 的完整内容,包含它们之间的区别、锁与 CPU 资源的释放、唤醒机制等内容,已整合前面内容:


Java 中 sleep()wait()notify()notifyAll() 对比

方法 所属类 是否释放锁 是否让出 CPU 唤醒方式 使用前提 是否抛异常
sleep(ms) Thread ❌ 否 ✅ 是 自动超时唤醒 不需要 synchronized ✅ 抛 InterruptedException
wait() Object ✅ 是 ✅ 是 notify() / notifyAll() 或超时 必须synchronized ✅ 抛 InterruptedException
wait(ms) Object ✅ 是 ✅ 是 时间到了 or 被唤醒 必须在 synchronized
notify() Object 唤醒一个 wait() 线程 必须在 synchronized
notifyAll() Object 唤醒所有 wait() 线程 必须在 synchronized

方法解释

Thread.sleep(ms)

  • 功能:让当前线程睡眠(暂停执行)一段时间
  • 不释放锁:如果持有 synchronized 锁,睡眠时仍占有该锁
  • 释放 CPU:当前线程暂停调度,其他线程有机会运行
  • 常见用途:模拟延迟、限速、轮询等
  • 异常:必须捕获或声明 InterruptedException
1
2
3
synchronized (lock) {
    Thread.sleep(1000); // 不释放 lock,其他线程无法进入该锁块
}

Object.wait() / wait(ms)

  • 功能:挂起线程,等待其他线程通知(或超时)
  • 释放锁:调用后立即释放当前持有的 monitor
  • 等待队列:进入对象的等待队列,直到被 notify() / notifyAll() 唤醒
  • 必须在 synchronized 中使用:否则抛出 IllegalMonitorStateException
    1
    2
    3
    4
    5
    6
    
    Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread is not owner
      at java.base/java.lang.Object.wait0(Native Method)
      at java.base/java.lang.Object.wait(Object.java:366)
      at com.example.demogc.Dermo1.get(Dermo1.java:23)
      at com.example.demogc.Dermo1$1.run(Dermo1.java:32)
      at java.base/java.lang.Thread.run(Thread.java:1583)
    
  • 超时版本:可以避免永久阻塞
  • 异常:会抛出 InterruptedException
1
2
3
4
5
synchronized (lock) {
    while (queue.isEmpty()) {
        lock.wait(); // 释放 lock,等待 notify 唤醒
    }
}

🔹 Object.notify()

  • 功能:随机唤醒一个正在 wait() 的线程
  • 不释放锁:notify 后当前线程继续持有锁,只有退出 synchronized 才会释放
  • 唤醒机制:被唤醒线程不会立刻执行,而是进入锁竞争队列,等待重新获得锁
  • 使用场景:条件满足后唤醒单个线程,例如有新数据到达队列
1
2
3
synchronized (lock) {
    lock.notify(); // 唤醒一个等待中的线程
}

🔹 Object.notifyAll()

  • 功能:唤醒所有等待该对象锁的线程
  • 适用场景:当有多个条件依赖于某一状态变化时使用
  • 机制同 notify:被唤醒线程重新竞争锁执行
1
2
3
synchronized (lock) {
    lock.notifyAll(); // 通知所有等待该锁的线程
}

🔁 调用时序图(简要描述)

1
2
3
4
5
6
7
8
9
线程A:wait()
 |
 |---> 释放锁,进入等待队列
 |
线程B:notify()
 |
 |---> 唤醒A,A转入阻塞队列(等待锁)
 |
A获得锁后继续执行

🧠 场景类比帮助理解

方法 类比场景
sleep() 自己设置闹钟睡觉,到点醒来,不管别人
wait() 在会议室外排队等通知,暂时让出座位
notify() 主持人通知某个等待的人进会议室
notifyAll() 主持人通知所有等待的人都进会议室排队竞争座位

weixin.png

公众号名称:怪味Coding
微信扫码关注或搜索公众号名称
This post is licensed under CC BY 4.0 by the author.

并发编程:Java 如何解决 可见性,有序性和原子性

并发编程:为什么并发编程容易出问题