一、Java 线程的几种状态(Thread.State

在 Java 中,线程有以下几种状态(java.lang.Thread.State 枚举):

  1. NEW(新建)

    • 线程对象被创建,但还没有调用 start() 方法。

    • 不会进入调度队列。

  2. RUNNABLE(可运行)

    • 线程已经调用了 start(),等待 CPU 调度。

    • 这里的 RUNNABLE 包含:

      • Ready(就绪):在 就绪队列(Ready Queue) 中,等待 CPU 时间片。

      • Running(运行中):正在占用 CPU 执行。

  3. BLOCKED(阻塞)

    • 线程在等待获取某个 对象锁(monitor)

    • 出现场景:synchronized 进入临界区失败。

    • 所在队列:锁的 EntryList(阻塞队列)

  4. WAITING(无限期等待)

    • 线程主动进入等待状态,直到被其他线程显式唤醒。

    • 出现场景:

      • Object.wait()(无超时)

      • LockSupport.park()

    • 所在队列:对象的 WaitSet(等待队列)

  5. TIMED_WAITING(限期等待)

    • 和 WAITING 类似,但有超时时间。

    • 出现场景:

      • Thread.sleep(timeout)

      • Object.wait(timeout)

      • join(timeout)

      • LockSupport.parkNanos() / parkUntil()

    • 所在队列:等待队列(WaitSet),带超时。

  6. TERMINATED(终止)

    • 线程执行完毕,生命周期结束,不会再进入任何队列。


二、线程在不同状态下的队列位置

  1. 就绪队列(Ready Queue)

    • 存放处于 RUNNABLE-Ready 的线程。

    • 等待 CPU 调度。

    • 特点:只有获得 CPU 时间片的线程才能进入 Running

  2. 阻塞队列(EntryList / Contention Queue)

    • 存放 BLOCKED 状态线程。

    • 线程因获取不到锁而阻塞。

    • 一旦锁被释放,JVM 会从该队列中唤醒一个或多个线程,进入就绪队列(不是立即运行)。

  3. 等待队列(WaitSet)

    • 存放 WAITING / TIMED_WAITING 状态的线程。

    • 线程主动调用 wait() / join() / sleep() 进入。

    • 必须通过 notify() / notifyAll() / 超时 才能退出。

    • 被唤醒后不会直接运行,而是进入 就绪队列 等待 CPU。


三、状态与队列的对应关系

状态 触发条件 所在队列 退出方式
NEW new Thread() 调用 start() → 就绪队列
RUNNABLE (Ready) start() 后 / 被唤醒 就绪队列 CPU 调度 → Running
RUNNING CPU 时间片分配 CPU 时间片完 / 阻塞 / 等待
BLOCKED 申请锁失败 阻塞队列(EntryList) 锁释放后 → 就绪队列
WAITING wait() / park() 等待队列(WaitSet) notify() / unpark() → 就绪队列
TIMED_WAITING wait(timeout) / sleep(timeout) 等待队列(WaitSet) 超时 / notify() → 就绪队列
TERMINATED run() 执行结束 生命周期结束

四、关键点总结

  1. 就绪队列:存放所有等待 CPU 的线程。

  2. 阻塞队列:存放获取不到锁的线程。

  3. 等待队列:存放执行 wait() / sleep() / join() 等等待操作的线程。

  4. notify()/notifyAll() 只会把线程从 等待队列 移动到 就绪队列,不直接运行。

  5. 锁释放 会把线程从 阻塞队列 移动到 就绪队列

Logo

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

更多推荐