多线程的生命周期

1. 介绍

Java 线程的生命周期由 JVM 管理,共 6 种状态,状态转换由线程调度、API 调用等触发:

  • NEW(新建):线程对象已经创建,但是未调用strat()方法,尚未启动。
  • RUNNABLE(可运行):线程已经启动,正在JVM中执行(或者等待CPU调度)。
  • BLOCKED(阻塞):线程等待获取对象锁(如进入synchronized代码块/方法时被占用)。
  • WAITING(等待):无限制等待,需要其他线程显式唤醒。
  • TIMED_WAITING(超时等待):有时限等待,超时自动唤醒。
  • TERMINATED(终止):线程执行完成(run()方法结束)或者异常终止。

注意RUNNABLE可以进一步细分,分为READY(就绪)和RUNING(运行)两种逻辑状态。

  • READY(就绪):线程已经具备执行条件,等待CPU调度(如刚启动,释放锁后)。
  • RUNNING(运行):线程正在CPU上执行run()方法。

(JVM没有显式区分这两种状态,统一归为RUNNABLE)。

阻塞态的区别

  • BLOCKED:仅针对对象锁竞争
  • WAITING/TIMED_WAITING:针对主动等待(如 wait ()、sleep ()),不属于锁竞争。

2. 线程之间的相互转换

如下图:
img_10.png

1. NEW

  • 含义:线程已创建,但尚未调用 start()
  • 可转换到:
    • RUNNABLE:调用 thread.start() 后。

❌ 不能直接进入其他任何状态(如 BLOCKED、WAITING 等)。


2. RUNNABLE

  • 含义:线程已启动,处于“就绪”或“正在运行”状态(包括等待 CPU 调度或正在执行)。
  • 可转换到:
    • BLOCKED:尝试进入 synchronized 块但锁被其他线程持有。
    • WAITING
      • 调用 Object.wait()(无超时)
      • 调用 Thread.join()(无超时)
      • 调用 LockSupport.park()
    • TIMED_WAITING
      • 调用 Thread.sleep(millis)
      • 调用 Object.wait(timeout)
      • 调用 Thread.join(timeout)
      • 调用 LockSupport.parkNanos() / parkUntil()
    • TERMINATED
      • run() 方法正常执行完毕
      • run() 抛出未捕获异常

⚠️ 注意:RUNNABLE 是唯一能通往所有其他非 NEW 状态的“枢纽”。


3. BLOCKED

  • 含义:线程正在等待获取 synchronized 监视器锁(monitor lock)。
  • 可转换到:
    • RUNNABLE:当所等待的锁被释放,且该线程成功获得锁后。

❌ 不能直接进入 WAITING、TIMED_WAITING 或 TERMINATED。
(必须先拿到锁 → 变成 RUNNABLE → 再执行后续代码才可能终止或等待)


4. WAITING

  • 含义:线程无限期等待另一个线程执行特定操作(如 notify()join() 完成)。
  • 可转换到:
    • BLOCKED
      • 仅适用于 Object.wait()notify()/notifyAll() 唤醒后,
      • 重新竞争 synchronized 锁失败时。
    • RUNNABLE
      • 被成功唤醒且立即获得所需锁(如 wait() 后锁可用)
      • join() 等待的线程已结束
      • LockSupport.unpark() 被调用
    • TERMINATED
      • 在 WAITING 中被中断(interrupt()),
      • 导致抛出 InterruptedException 且未处理,使 run() 退出。

❌ 不能直接进入 TIMED_WAITING 或 NEW。


5. TIMED_WAITING

  • 含义:线程等待指定时间,或直到被唤醒/中断。
  • 可转换到:
    • BLOCKED
      • 仅当因 Object.wait(timeout)notify() 唤醒,
      • 重新获取 synchronized 锁失败时。
    • RUNNABLE
      • 超时时间到达(如 sleep(1000) 结束)
      • 被提前唤醒且锁可用(如 wait(5000)notify() 唤醒且锁空闲)
      • join(timeout) 等待的线程已结束
    • TERMINATED
      • 被中断(interrupt())导致 InterruptedException
      • 且异常未被捕获,使 run() 方法退出。

❌ 不能直接进入 WAITING 或 NEW。


6. TERMINATED

  • 含义:线程已执行完毕(正常或异常结束)。
  • 可转换到:
    • !这是最终状态,不可逆。

一旦 TERMINATED,线程对象不能再被启动或复用。


📊 总结表格(箭头表示“可以转换到”)

当前状态 可转换到的状态
NEW → RUNNABLE
RUNNABLE → BLOCKED, WAITING, TIMED_WAITING, TERMINATED
BLOCKED → RUNNABLE
WAITING → BLOCKED, RUNNABLE, TERMINATED
TIMED_WAITING → BLOCKED, RUNNABLE, TERMINATED
TERMINATED → (无)

💡 补充说明:

  • 所有状态转换均由 JVM 自动管理,程序员只能通过调用方法(如 start(), wait(), interrupt()间接影响状态。
  • BLOCKED 仅与 synchronized 锁竞争有关;使用 ReentrantLock 等显式锁不会进入 BLOCKED,而是 WAITING
  • RUNNABLE 在操作系统层面包含 READY(就绪)RUNNING(运行中),但在 Java 中统一为一个状态。