深入浅出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 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui