深入浅出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输出的线程堆栈

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

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

相关推荐
weixin_411191844 分钟前
原生安卓与flutter混编的实现
android·flutter
呼啸长风24 分钟前
记一次未成功的 MMKV Pull Request
android·ios·开源
小墙程序员2 小时前
Android 性能优化(六)使用 Callstacks Sample 和 Java/Kotlin Method Recording 分析方法的耗时
android·性能优化·android studio
hcgeng4 小时前
android中相近方法对比
android·方法比对
这儿有一堆花5 小时前
eSIM技术深度解析:从物理芯片到数字革命
android·ios
雨白7 小时前
开发 SunnyWeather:Android 天气预报 App(下)
android
_extraordinary_8 小时前
Java 字符串常量池 +反射,枚举和lambda表达式
android·java·开发语言
alexhilton8 小时前
学会说不!让你彻底学会Kotlin Flow的取消机制
android·kotlin·android jetpack
来来走走9 小时前
Flutter dart运算符
android·前端·flutter