
目录一、Java线程的6种标准状态二、每种线程状态的具体含义结合官方定义实例1. NEW新建状态线程已创建但尚未启动2. RUNNABLE可运行状态等待调度或正在执行3. BLOCKED阻塞状态等待监视器锁synchronized4. WAITING无限期等待状态无限期等待特定操作5. TIMED_WAITING超时等待状态指定时间内等待6. TERMINATED终止状态线程已执行完毕或异常终止三、线程状态之间的切换条件1. 核心状态切换流程2. 具体切换条件详解结合官方定义四、常见误区五、总结在Java并发编程中线程是核心执行单元其状态的变化直接决定了程序的运行效率和正确性。很多开发者在学习线程时容易混淆线程的不同状态以及状态之间的切换条件——比如“NEW状态”和“RUNNABLE状态”有何关联“BLOCKED状态”“WAITING状态”和“TIMED_WAITING状态”到底有何区别今天这篇博客就结合Java官方标准java.lang.Thread.State枚举类系统总结Java线程的6种标准状态结合原理和实例把每个状态的含义、触发条件以及切换逻辑讲清楚帮你彻底理清线程状态的来龙去脉。一、Java线程的6种标准状态首先要明确核心前提Java线程的状态由JVM严格定义封装在java.lang.Thread.State枚举类中共6种标准状态并非操作系统层面的线程状态操作系统线程通常有就绪、运行、阻塞等状态与Java线程状态有对应关系但不完全一致。Java线程的6种标准状态及核心描述如下这6种状态覆盖了线程从创建到销毁的全生命周期状态描述NEW线程已创建但尚未启动RUNNABLE线程正在JVM中执行等待操作系统调度包含就绪和运行两种逻辑状态BLOCKED线程被阻塞等待监视器锁synchronized锁WAITING线程无限期等待另一个线程执行特定操作TIMED_WAITING线程在指定时间内等待另一个线程执行操作或超时自动唤醒TERMINATED线程已执行完毕或异常终止这里需要特别说明此前部分资料会将“就绪”和“运行”拆分为两个逻辑状态但根据Java官方定义这两种情况统一归为RUNNABLE状态——因为从JVM层面来看无论是等待CPU调度就绪还是正在执行运行线程都处于“可运行”的范畴唯一的区别是是否获得CPU执行权。而BLOCKED、WAITING、TIMED_WAITING均属于“非运行状态”即线程暂时无法获取CPU执行权需等待特定条件满足后才能恢复。二、每种线程状态的具体含义结合官方定义实例下面逐一解析6种标准状态的详细含义、典型触发场景结合代码示例帮助大家快速联想避免死记硬背同时贴合官方枚举类的定义规范。1. NEW新建状态线程已创建但尚未启动当我们通过new Thread()创建一个线程对象时线程就进入了NEW状态。此时JVM已经为线程分配了内存存储线程对象的信息如线程名称、优先级等但尚未调用线程的start()方法线程的执行逻辑run()方法完全没有开始。核心特征线程对象已存在但未与操作系统的底层线程关联没有真正启动执行。典型场景// 线程进入NEW状态仅创建对象未启动 Thread thread new Thread(() - { System.out.println(线程执行逻辑); }); // 此时thread.getState()返回Thread.State.NEW注意此时线程还没有与操作系统的线程关联只有调用start()方法后JVM才会请求操作系统创建一个新的底层线程线程才会脱离NEW状态。2. RUNNABLE可运行状态等待调度或正在执行当线程调用start()方法后线程就进入了RUNNABLE状态。这是Java官方定义的核心状态包含两种逻辑场景均对应操作系统的“就绪状态”就绪场景线程已与操作系统底层线程关联JVM将其放入“就绪队列”等待CPU调度具备所有运行所需条件仅缺少CPU执行权运行场景线程获得CPU时间片正在执行run()方法中的逻辑。从JVM视角来看这两种场景无需区分统一归为RUNNABLE状态——因为线程是否能执行取决于CPU调度而非JVM控制。典型场景Thread thread new Thread(() - { System.out.println(线程执行逻辑); }); thread.start(); // 调用start()后线程进入RUNNABLE状态 // 此时thread.getState()返回Thread.State.RUNNABLE无论是否获得CPU补充RUNNABLE状态是一个“动态过渡状态”线程不会一直停留在这个状态——要么获得CPU时间片执行逻辑要么因某些原因如获取锁失败、调用等待方法脱离该状态进入BLOCKED、WAITING或TIMED_WAITING状态。3. BLOCKED阻塞状态等待监视器锁synchronized根据官方定义BLOCKED状态的唯一触发原因是线程试图获取一个被其他线程持有的监视器锁即synchronized锁包括同步方法、同步代码块的锁此时线程会被阻塞直到成功获取到锁才能恢复到RUNNABLE状态。核心特征仅因“获取synchronized锁失败”而阻塞其他阻塞场景如等待通知、超时等待不属于该状态。典型场景Object lock new Object(); // 线程1先获取锁进入RUNNABLE状态并执行 Thread thread1 new Thread(() - { synchronized (lock) { try { Thread.sleep(1000); // 后续会进入TIMED_WAITING状态 } catch (InterruptedException e) { e.printStackTrace(); } } }); // 线程2试图获取锁但锁被线程1持有进入BLOCKED状态 Thread thread2 new Thread(() - { synchronized (lock) { // 此处阻塞进入BLOCKED状态 System.out.println(线程2执行); } }); thread1.start(); thread2.start(); // 线程2启动后getState()返回Thread.State.BLOCKED4. WAITING无限期等待状态无限期等待特定操作WAITING状态是“无限期等待”即线程会一直等待直到另一个线程执行特定的唤醒操作如Object.notify()、Object.notifyAll()否则会一直处于等待状态无法自动恢复。核心触发条件线程主动调用以下方法会进入WAITING状态调用后会释放持有的监视器锁Object.wait()无超时参数需其他线程调用同一对象的notify()或notifyAll()唤醒Thread.join()无超时参数等待目标线程执行完毕后自动唤醒LockSupport.park()无超时参数需其他线程调用LockSupport.unpark(Thread)唤醒。典型场景Object lock new Object(); Thread thread1 new Thread(() - { synchronized (lock) { try { lock.wait(); // 调用无参wait()进入WAITING状态释放锁 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(线程1被唤醒); } }); Thread thread2 new Thread(() - { synchronized (lock) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } lock.notify(); // 唤醒thread1使其从WAITING恢复为RUNNABLE } }); thread1.start(); thread2.start();5. TIMED_WAITING超时等待状态指定时间内等待TIMED_WAITING状态是“有限期等待”与WAITING状态的核心区别是线程等待一段时间后若未被其他线程唤醒会自动唤醒恢复到RUNNABLE状态若在超时前被唤醒也会提前恢复。核心触发条件线程调用带有超时参数的等待方法会进入TIMED_WAITING状态部分方法会释放监视器锁Thread.sleep(long millis)睡眠指定时间不释放锁超时后自动唤醒Object.wait(long timeout)等待指定时间释放锁超时或被唤醒后恢复Thread.join(long millis)等待目标线程指定时间超时或目标线程执行完毕后恢复LockSupport.parkNanos(long nanos)、LockSupport.parkUntil(long deadline)超时等待需唤醒或超时后恢复。典型场景// 场景1Thread.sleep()触发TIMED_WAITING不释放锁 Thread thread1 new Thread(() - { try { Thread.sleep(1000); // 睡眠1秒进入TIMED_WAITING状态 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(线程1超时自动唤醒); }); // 场景2Object.wait(long)触发TIMED_WAITING释放锁 Object lock new Object(); Thread thread2 new Thread(() - { synchronized (lock) { try { lock.wait(1000); // 等待1秒超时自动唤醒或被notify()唤醒 } catch (InterruptedException e) { e.printStackTrace(); } } }); thread1.start(); thread2.start();6. TERMINATED终止状态线程已执行完毕或异常终止TERMINATED是线程的最终状态一旦进入该状态线程就会被JVM回收无法再切换到其他任何状态也无法通过start()方法重新启动。进入终止状态的两种情况正常终止线程的run()方法执行完毕逻辑正常结束线程自然终止异常终止线程在运行过程中抛出未捕获的异常如NullPointerException、InterruptedException导致线程被迫终止。典型场景// 正常终止run()方法执行完毕 Thread thread1 new Thread(() - { System.out.println(线程1执行完毕); // run()执行完进入TERMINATED状态 }); // 异常终止抛出未捕获异常 Thread thread2 new Thread(() - { int i 1 / 0; // 抛出ArithmeticException线程被迫终止 }); thread1.start(); thread2.start(); // 线程执行完毕后getState()返回Thread.State.TERMINATED注意调用线程的stop()方法也能强制终止线程但该方法已被废弃会导致线程资源无法正常释放引发数据不一致问题不推荐使用。三、线程状态之间的切换条件线程的6种状态之间并非孤立存在而是会根据不同的操作和场景相互切换。1. 核心状态切换流程NEW→RUNNABLE→BLOCKED / WAITING / TIMED_WAITING→RUNNABLE→TERMINATED补充说明RUNNABLE状态可直接切换到BLOCKED、WAITING、TIMED_WAITING状态也可直接切换到TERMINATED状态BLOCKED、WAITING、TIMED_WAITING状态无法直接切换到TERMINATED状态必须先恢复为RUNNABLE状态再由RUNNABLE状态切换到TERMINATEDNEW状态只能切换到RUNNABLE状态无法直接切换到其他状态TERMINATED状态无法切换到任何其他状态。2. 具体切换条件详解结合官方定义NEW → RUNNABLE触发条件调用线程的start()方法。说明new Thread()只是创建线程对象NEW状态调用start()后JVM请求操作系统创建底层线程线程进入可运行状态等待CPU调度。RUNNABLE → BLOCKED触发条件线程试图获取synchronized监视器锁且该锁被其他线程持有。说明获取锁失败后线程从RUNNABLE状态进入BLOCKED状态当持有锁的线程释放锁且当前线程成功获取锁会从BLOCKED状态恢复为RUNNABLE状态。RUNNABLE → WAITING触发条件线程调用无超时参数的等待方法Object.wait()、Thread.join()、LockSupport.park()。说明调用这些方法后线程主动放弃CPU执行权进入无限期等待被其他线程唤醒后恢复为RUNNABLE状态。RUNNABLE → TIMED_WAITING触发条件线程调用带有超时参数的等待方法Thread.sleep(long)、Object.wait(long)、Thread.join(long)等。说明线程进入有限期等待要么超时后自动唤醒要么被其他线程提前唤醒两种情况都会恢复为RUNNABLE状态。BLOCKED → RUNNABLE触发条件线程成功获取到之前未获取到的synchronized监视器锁。WAITING → RUNNABLE触发条件其他线程执行唤醒操作如Object.notify()、LockSupport.unpark()或目标线程执行完毕Thread.join()场景。TIMED_WAITING → RUNNABLE触发条件等待时间超时或其他线程执行唤醒操作。RUNNABLE → TERMINATED触发条件① run()方法执行完毕正常终止② 线程运行过程中抛出未捕获的异常异常终止③ 不推荐调用Thread.stop()方法强制终止。NEW → TERMINATED特殊情况线程创建后NEW状态未调用start()方法线程对象被垃圾回收这种情况极少出现实际开发中可忽略。四、常见误区学习线程状态时很多开发者会有一些常见的误解这里结合官方定义逐一澄清帮你避开坑点 误区1调用start()方法会立即执行线程逻辑 纠正不会。调用start()后线程进入RUNNABLE状态等待CPU调度只有获得时间片后才会执行run()方法并非立即执行。 误区2Thread.sleep()会释放synchronized锁 纠正不会。sleep()方法只会让线程进入TIMED_WAITING状态放弃CPU执行权但不会释放线程持有的synchronized锁而Object.wait()方法会释放锁。 误区3BLOCKED状态和WAITING状态没有区别 纠正区别极大。BLOCKED仅因“获取synchronized锁失败”触发而WAITING是线程主动调用无超时等待方法触发且BLOCKED状态会在锁释放后自动竞争锁WAITING状态必须依赖其他线程唤醒。 误区4线程终止后还能调用start()方法重新启动 纠正不能。线程一旦进入TERMINATED状态就会被JVM回收无法再调用start()方法启动否则会抛出IllegalThreadStateException异常。 误区5RUNNABLE状态就是线程正在执行 纠正不是。RUNNABLE状态包含“就绪”和“运行”两种逻辑场景只有当线程获得CPU时间片时才会执行run()方法未获得时间片时只是等待调度。五、总结Java线程的6种标准状态NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED是Java并发编程的基础其定义严格遵循JVM规范覆盖了线程从创建到销毁的全生命周期。理解线程状态的关键不仅要记住每种状态的官方描述更要掌握状态之间的切换条件——尤其是区分BLOCKED、WAITING、TIMED_WAITING三种非运行状态的触发场景这是面试中高频考察的重点也是后续学习线程同步、线程池、锁机制的基础。最后建议大家结合代码实例亲自调试线程的状态通过Thread.getState()方法获取当前线程状态观察状态切换的过程通过实践加深理解避免死记硬背。只有真正掌握线程状态才能在并发编程中规避线程安全问题提升程序的运行效率。