核心速览

  • Java 线程生命周期包含 6 种标准状态java.lang.Thread.State):
    NEWRUNNABLE →(BLOCKED / WAITING / TIMED_WAITING)→ TERMINATED
  • 任意时刻,线程仅处于一种状态;这些是 JVM 逻辑状态,不等同于操作系统线程状态。
  • 虚拟线程(JDK 21+)与平台线程共享完全相同的状态模型,但阻塞行为更高效:可自动卸载载体线程,避免 OS 线程浪费。
  • 关键区别
    • BLOCKED:仅由竞争 synchronized monitor 锁引起;
    • WAITING / TIMED_WAITING:由 wait()join()sleep()LockSupport.park() 等主动等待操作触发;
    • 显式锁(如 ReentrantLock)不会导致 BLOCKED,而是进入 WAITINGTIMED_WAITING
  • 终止线程应使用协作式中断(interrupt()禁用已废弃的 stop()(会导致资源/锁泄漏)。

Java 线程的生命周期描述了一个线程从创建到销毁所经历的各个状态。自 Java 5 引入 java.lang.Thread.State 枚举以来,线程状态模型已标准化,并在后续 JDK 版本(包括 JDK 21)中保持稳定。

值得注意的是,尽管 JDK 21 引入了虚拟线程(Virtual Threads),其生命周期状态模型与平台线程(Platform Threads)完全一致,均遵循以下六种状态:

  • NEW(新建)
  • RUNNABLE(可运行 / 运行)
  • BLOCKED(阻塞)
  • WAITING(无时限等待)
  • TIMED_WAITING(有时限等待)
  • TERMINATED(终止)

这些状态在 java.lang.Thread.State 枚举中有明确定义,且 一个线程在任意时刻只能处于其中一种状态。这些是 JVM 层面的逻辑状态不直接对应操作系统线程状态

在操作系统层面,BLOCKEDWAITINGTIMED_WAITING 通常可视为“休眠状态”——处于这些状态的线程不会获得 CPU 使用权

start()

waiting for monitor lock

Object.wait()
Thread.join()
LockSupport.park()

Thread.sleep()
Object.wait(timeout)
Thread.join(timeout)
LockSupport.parkNanos()

run() completes
or exception

acquired monitor lock

Object.notify()
Object.notifyAll()
Thread dies
LockSupport.unpark()

timeout expires
or explicitly notified

NEW

RUNNABLE

BLOCKED

WAITING

TIMED_WAITING

TERMINATED

RUNNABLE

包含就绪(Ready)和运行(Running)两种状态


1、NEW(新建)

线程对象已被创建(通过 new Thread()),但 尚未调用 start() 方法

  • 线程未被 JVM 调度;
  • 不占用系统线程资源(对虚拟线程而言,也尚未被调度器注册)。
Thread t = new Thread(() -> {});
// t.getState() == Thread.State.NEW

2、RUNNABLE(可运行 / 运行)

线程已调用 start(),处于 就绪(等待 CPU 时间片)或运行(正在 CPU 上执行) 状态。

  • JVM 将这两种情况统一归为 RUNNABLE
  • 应用层无法区分,切换由操作系统调度器处理;
  • 对于虚拟线程:当有工作且未被阻塞时,也处于此状态,等待载体平台线程执行。

即使线程正在执行 I/O(如 System.in.read()),只要未被 JVM 识别为‘可卸载阻塞’,平台线程仍处于 RUNNABLE,但实际在 OS 层可能阻塞。


3、BLOCKED(阻塞)

线程正在 等待 monitor 锁,以便进入 synchronized 块或方法,或在 Object.wait() 后重新进入同步块。

  • 触发场景:尝试获取已被其他线程持有的 synchronized 锁;
  • 一旦锁被释放,JVM 会从阻塞队列中唤醒线程竞争锁;
  • 仅适用于 synchronized
  • 使用 ReentrantLock 等显式锁导致的等待,线程会进入 WAITINGTIMED_WAITING而非 BLOCKED

4、WAITING(无时限等待)

线程主动放弃 CPU,进入无限期等待,直到被其他线程显式唤醒

常见触发方法:

  • Object.wait()(无超时)
  • Thread.join()(无超时)
  • LockSupport.park()

唤醒方式:

  • Object.notify() / Object.notifyAll()
  • join() 的线程终止
  • LockSupport.unpark(thread)

流转图

RUNNABLE 
  → (enter synchronized) → holds lock
  → Object.wait() → releases lock → WAITING
  → notify() → tries to reacquire lock → BLOCKED
  → acquires lock → RUNNABLE

5、TIMED_WAITING(有时限等待)

线程等待指定时间后自动唤醒,也可被提前唤醒。是 WAITING 的超时版本,用于实现定时、超时控制等。

触发方法:

  • Thread.sleep(long millis)
  • Object.wait(long timeout)
  • Thread.join(long millis)
  • LockSupport.parkNanos(long nanos)
  • LockSupport.parkUntil(long deadline)

6、TERMINATED(终止)

线程已完成执行run() 正常结束)或因未捕获异常而终止

  • 一旦进入此状态,无法重启
  • 再次调用 start() 会抛出 IllegalThreadStateException

7、虚拟线程(JDK 21+)

Project Loom 引入的虚拟线程在生命周期状态上完全兼容上述六种状态。

  • 调用 Thread.start() 后进入 RUNNABLE
  • 执行 I/O、synchronizedLockSupport.park() 等操作时,会进入 BLOCKEDWAITINGTIMED_WAITING
  • 关键区别
    • 平台线程:阻塞(如 I/O)会阻塞底层 OS 线程
    • 虚拟线程:遇到可卸载的阻塞操作(如多数 I/O),JVM 会自动释放载体平台线程,使其执行其他虚拟线程,从而实现高并发;
  • 状态转换语义与平台线程完全一致

彩蛋:stop()interrupt()

方法 描述
stop() 已废弃。直接强制终止线程,不释放锁(如 ReentrantLock),可能导致其他线程永久无法获取锁,引发死锁或数据不一致。类似方法 suspend() / resume() 同样不安全,不应使用
interrupt() 推荐方式。仅发送中断信号,线程可选择:
- 通过 InterruptedException 响应(如 sleep()wait());
- 主动检查 Thread.interrupted()isInterrupted()
- 忽略中断(但不符合协作式中断规范)。
这是一种协作式中断机制,保证资源清理与状态一致性。

一键三连,让我的信心像气球一样膨胀!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐