Java中的线程状态与转换机制详解
字数 1331 2025-11-11 09:10:01

Java中的线程状态与转换机制详解

一、线程状态的基本概念
在Java中,线程的生命周期被定义为6种状态,这些状态在Thread.State枚举中明确列出:

  1. NEW(新建状态)
  2. RUNNABLE(可运行状态)
  3. BLOCKED(阻塞状态)
  4. WAITING(等待状态)
  5. TIMED_WAITING(计时等待状态)
  6. TERMINATED(终止状态)

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

  1. NEW状态
  • 描述:线程对象刚被创建,但尚未调用start()方法
  • 特征:此时线程还未被系统调度执行
  • 示例代码:
Thread thread = new Thread(() -> {});
System.out.println(thread.getState()); // 输出NEW
  1. NEW → RUNNABLE
  • 触发条件:调用线程的start()方法
  • 过程:JVM为线程分配系统资源,将其加入就绪队列等待CPU调度
  • 注意:不能重复调用start()方法,否则会抛出IllegalThreadStateException
  1. RUNNABLE状态详解
  • 包含两个子状态:就绪(Ready)和运行中(Running)
  • 就绪:线程已准备好,等待CPU时间片
  • 运行中:线程正在CPU上执行
  • 状态判断:无法通过API区分就绪和运行中,都显示为RUNNABLE
  1. RUNNABLE → BLOCKED
  • 触发条件:线程尝试获取一个被其他线程持有的同步锁(synchronized)
  • 典型场景:多个线程竞争同一个对象的监视器锁
  • 示例:
synchronized (lock) {
    // 当线程A持有锁时,线程B尝试进入会进入BLOCKED状态
}
  1. RUNNABLE → WAITING
  • 触发方式:
    • 调用Object.wait()方法(需先获得对象锁)
    • 调用Thread.join()方法(不带超时参数)
    • 调用LockSupport.park()方法
  • 特征:无限期等待,需要其他线程显式唤醒
  1. WAITING → RUNNABLE
  • 唤醒方式:
    • Object.notify()/notifyAll()(对应wait())
    • 被join的线程执行完毕
    • LockSupport.unpark(thread)
  1. RUNNABLE → TIMED_WAITING
  • 触发方式(带超时参数):
    • Thread.sleep(long millis)
    • Object.wait(long timeout)
    • Thread.join(long millis)
    • LockSupport.parkNanos()/parkUntil()
  • 特征:在指定时间后自动唤醒或提前被中断
  1. 状态转换完整流程图
NEW --start()--> RUNNABLE --获锁失败--> BLOCKED
  |
  |--执行完毕--> TERMINATED
  |
  |--wait()/join()--> WAITING
  |        ↑
  |--notify()/interrupt()--
  |
  |--sleep()/wait(timeout)--> TIMED_WAITING

三、重要注意事项

  1. 中断机制
  • 调用thread.interrupt()可中断WAITING/TIMED_WAITING状态
  • 被中断的线程会抛出InterruptedException,并清除中断标志
  1. 状态监控实战
public class ThreadStateMonitor {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        
        Thread thread = new Thread(() -> {
            synchronized (lock) {
                try {
                    Thread.sleep(1000); // TIMED_WAITING
                    lock.wait();        // WAITING
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        System.out.println("创建后:" + thread.getState()); // NEW
        
        thread.start();
        Thread.sleep(100); // 确保thread进入同步块
        System.out.println("启动后:" + thread.getState()); // TIMED_WAITING或BLOCKED
        
        Thread.sleep(2000);
        System.out.println("wait后:" + thread.getState()); // WAITING
    }
}

四、常见面试问题分析

  1. BLOCKED和WAITING的区别?
  • BLOCKED:在等待获取监视器锁,是主动的竞争状态
  • WAITING:等待其他线程的显式唤醒,是被动的等待状态
  1. sleep()和wait()的异同?
  • 相同点:都会让线程暂停执行
  • 不同点:
    • sleep()不释放锁,wait()会释放锁
    • sleep()是Thread的方法,wait()是Object的方法
    • sleep()自动唤醒,wait()需要被唤醒

理解线程状态转换机制对于多线程编程、死锁排查和性能优化都具有重要意义,是Java并发编程的基础核心知识。

Java中的线程状态与转换机制详解 一、线程状态的基本概念 在Java中,线程的生命周期被定义为6种状态,这些状态在Thread.State枚举中明确列出: NEW(新建状态) RUNNABLE(可运行状态) BLOCKED(阻塞状态) WAITING(等待状态) TIMED_ WAITING(计时等待状态) TERMINATED(终止状态) 二、详细状态解析与转换过程 NEW状态 描述:线程对象刚被创建,但尚未调用start()方法 特征:此时线程还未被系统调度执行 示例代码: NEW → RUNNABLE 触发条件:调用线程的start()方法 过程:JVM为线程分配系统资源,将其加入就绪队列等待CPU调度 注意:不能重复调用start()方法,否则会抛出IllegalThreadStateException RUNNABLE状态详解 包含两个子状态:就绪(Ready)和运行中(Running) 就绪:线程已准备好,等待CPU时间片 运行中:线程正在CPU上执行 状态判断:无法通过API区分就绪和运行中,都显示为RUNNABLE RUNNABLE → BLOCKED 触发条件:线程尝试获取一个被其他线程持有的同步锁(synchronized) 典型场景:多个线程竞争同一个对象的监视器锁 示例: RUNNABLE → WAITING 触发方式: 调用Object.wait()方法(需先获得对象锁) 调用Thread.join()方法(不带超时参数) 调用LockSupport.park()方法 特征:无限期等待,需要其他线程显式唤醒 WAITING → RUNNABLE 唤醒方式: Object.notify()/notifyAll()(对应wait()) 被join的线程执行完毕 LockSupport.unpark(thread) RUNNABLE → TIMED_ WAITING 触发方式(带超时参数): Thread.sleep(long millis) Object.wait(long timeout) Thread.join(long millis) LockSupport.parkNanos()/parkUntil() 特征:在指定时间后自动唤醒或提前被中断 状态转换完整流程图 三、重要注意事项 中断机制 调用thread.interrupt()可中断WAITING/TIMED_ WAITING状态 被中断的线程会抛出InterruptedException,并清除中断标志 状态监控实战 四、常见面试问题分析 BLOCKED和WAITING的区别? BLOCKED:在等待获取监视器锁,是主动的竞争状态 WAITING:等待其他线程的显式唤醒,是被动的等待状态 sleep()和wait()的异同? 相同点:都会让线程暂停执行 不同点: sleep()不释放锁,wait()会释放锁 sleep()是Thread的方法,wait()是Object的方法 sleep()自动唤醒,wait()需要被唤醒 理解线程状态转换机制对于多线程编程、死锁排查和性能优化都具有重要意义,是Java并发编程的基础核心知识。