深入浅出Java线程状态

在Java中,线程的状态 是通过Thread.State枚举明确定义的,共分为6种状态。理解这些状态及其转换关系是掌握多线程编程的基础。下面我会结合源码、流程图和实际代码示例,帮你彻底理清线程的生命周期。


一、Java线程的6种状态(Thread.State枚举)

java 复制代码
public enum State {
    NEW,          // 线程刚创建,未启动
    RUNNABLE,     // 可运行状态(可能在运行或等待CPU调度)
    BLOCKED,      // 被阻塞(等待监视器锁)
    WAITING,      // 无限期等待(直到被显式唤醒)
    TIMED_WAITING, // 有限期等待(自动唤醒)
    TERMINATED    // 线程已终止
}

二、详细状态解析与转换流程图

状态转换图:

stateDiagram-v2 [*] --> NEW NEW --> RUNNABLE: start() RUNNABLE --> BLOCKED: 竞争锁失败 BLOCKED --> RUNNABLE: 获取到锁 RUNNABLE --> WAITING: wait()/join()/park() WAITING --> RUNNABLE: notify()/unpark() RUNNABLE --> TIMED_WAITING: sleep(ms)/wait(ms) TIMED_WAITING --> RUNNABLE: 超时/notify() RUNNABLE --> TERMINATED: run()执行完毕

状态详解:

  1. NEW(新建)

    • 线程对象已创建但未调用start()

    • 示例:

      java 复制代码
      Thread thread = new Thread(() -> {});
      System.out.println(thread.getState()); // 输出 NEW
  2. RUNNABLE(可运行)

    • 包含两种子状态:
      • Ready:等待CPU调度(线程在就绪队列中)
      • Running:正在执行(占用CPU)
    • 触发条件:调用start()后进入该状态
    • 注意:IO阻塞(如Socket读写)不会改变状态,仍为RUNNABLE
  3. BLOCKED(阻塞)

    • 线程未能获取synchronized锁时的状态

    • 示例:

      java 复制代码
      synchronized (lock) {
          // 其他线程尝试进入时会阻塞
      }
  4. WAITING(无限等待)

    • 需要被其他线程显式唤醒

    • 触发方法:

      • Object.wait()(需配合notify())
      • Thread.join()(等待目标线程终止)
      • LockSupport.park()
    • 示例:

      java 复制代码
      synchronized (lock) {
          lock.wait(); // 进入WAITING
      }
  5. TIMED_WAITING(超时等待)

    • 带时间限制的等待,超时后自动唤醒

    • 触发方法:

      • Thread.sleep(long ms)
      • Object.wait(long timeout)
      • LockSupport.parkNanos()
    • 示例:

      java 复制代码
      Thread.sleep(1000); // 进入TIMED_WAITING
  6. TERMINATED(终止)

    • 线程执行完run()方法或抛出未捕获异常

    • 示例:

      java 复制代码
      thread.start();
      thread.join();
      System.out.println(thread.getState()); // 输出 TERMINATED

三、关键状态转换的代码验证

java 复制代码
public class ThreadStateDemo {
    public static void main(String[] args) throws Exception {
        Object lock = new Object();
        
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    lock.wait(1000); // TIMED_WAITING
                } catch (InterruptedException e) {}
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (lock) {
                try {
                    Thread.sleep(Long.MAX_VALUE); // TIMED_WAITING
                } catch (InterruptedException e) {}
            }
        });

        Thread t3 = new Thread(() -> {
            synchronized (lock) {
                // 竞争锁失败会BLOCKED
            }
        });

        System.out.println("t1: " + t1.getState()); // NEW
        
        t1.start();
        t2.start();
        Thread.sleep(50); // 确保t1/t2进入同步块
        System.out.println("t1: " + t1.getState()); // TIMED_WAITING (wait(1000))
        System.out.println("t2: " + t2.getState()); // TIMED_WAITING (sleep)
        
        t3.start();
        Thread.sleep(50); // 确保t3开始竞争锁
        System.out.println("t3: " + t3.getState()); // BLOCKED
        
        synchronized (lock) {
            lock.notifyAll(); // 唤醒t1
        }
        Thread.sleep(50);
        System.out.println("t1: " + t1.getState()); // TERMINATED
    }
}

四、WAITING vs BLOCKED 的本质区别

状态 触发条件 唤醒方式 典型场景
BLOCKED 竞争synchronized锁失败 锁释放时系统自动分配 多线程竞争同步锁
WAITING 主动调用等待方法 需其他线程显式唤醒 线程间协作(生产者消费者)

五、高频面试题深度解析

  1. sleep()wait()的区别?

    • sleep()是Thread的静态方法,不释放锁,进入TIMED_WAITING;
    • wait()是Object的方法,释放锁,需在同步块中调用。
  2. 如何强制终止线程?

    • 已废弃:Thread.stop()(会导致资源未释放)
    • 正确做法:通过interrupt()中断 + 线程内检查标志位
  3. RUNNABLE状态是否一定在运行?

    • 不一定!可能是就绪状态(等待CPU时间片),可用jstack工具查看实际运行状态。

掌握这些状态转换关系后,你就能:

✅ 精准分析jstack输出的线程堆栈

✅ 设计合理的线程协作逻辑

✅ 快速定位死锁/线程泄漏问题

相关推荐
鸿蒙布道师1 小时前
鸿蒙NEXT开发动画案例5
android·ios·华为·harmonyos·鸿蒙系统·arkui·huawei
橙子199110167 小时前
在 Kotlin 中什么是委托属性,简要说说其使用场景和原理
android·开发语言·kotlin
androidwork7 小时前
Kotlin Android LeakCanary内存泄漏检测实战
android·开发语言·kotlin
笨鸭先游8 小时前
Android Studio的jks文件
android·ide·android studio
gys98958 小时前
android studio开发aar插件,并用uniapp开发APP使用这个aar
android·uni-app·android studio
H309198 小时前
vue3+dhtmlx-gantt实现甘特图展示
android·javascript·甘特图
像风一样自由8 小时前
【001】renPy android端启动流程分析
android·gitee
千里马学框架10 小时前
重学安卓14/15自由窗口freeform企业实战bug-学员作业
android·framework·bug·systrace·安卓framework开发·安卓窗口系统·自由窗口
xianrenli3815 小时前
android特许权限调试
android
*拯18 小时前
Uniapp Android/IOS 获取手机通讯录
android·ios·uni-app