云计算百科
云计算领域专业知识百科平台

Java | 线程 - 生命周期

生命周期

1 整体生命周期状态图

经典图:清晰区分 NEW → RUNNABLE(就绪+运行)→ BLOCKED / WAITING / TIMED_WAITING → TERMINATED,并标注了所有进入方式。

image-20260227091339104

五状态经典图:新建 → 就绪 → 运行 → 阻塞 → 死亡。

Untitled-2025-12-11-2114.excalidraw

超级详细版(带文字说明):把就绪细分为“等待CPU”和“运行中”,阻塞分为各种场景,非常适合深入理解。

#mermaid-svg-jvGw7XGKrhRKPI0b{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jvGw7XGKrhRKPI0b .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jvGw7XGKrhRKPI0b .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jvGw7XGKrhRKPI0b .error-icon{fill:#552222;}#mermaid-svg-jvGw7XGKrhRKPI0b .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jvGw7XGKrhRKPI0b .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jvGw7XGKrhRKPI0b .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jvGw7XGKrhRKPI0b .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jvGw7XGKrhRKPI0b .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jvGw7XGKrhRKPI0b .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jvGw7XGKrhRKPI0b .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jvGw7XGKrhRKPI0b .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jvGw7XGKrhRKPI0b .marker.cross{stroke:#333333;}#mermaid-svg-jvGw7XGKrhRKPI0b svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jvGw7XGKrhRKPI0b p{margin:0;}#mermaid-svg-jvGw7XGKrhRKPI0b defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-jvGw7XGKrhRKPI0b g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-jvGw7XGKrhRKPI0b g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-jvGw7XGKrhRKPI0b g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-jvGw7XGKrhRKPI0b g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-jvGw7XGKrhRKPI0b g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-jvGw7XGKrhRKPI0b .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-jvGw7XGKrhRKPI0b .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-jvGw7XGKrhRKPI0b .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-jvGw7XGKrhRKPI0b .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-jvGw7XGKrhRKPI0b .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-jvGw7XGKrhRKPI0b .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-jvGw7XGKrhRKPI0b .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-jvGw7XGKrhRKPI0b .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jvGw7XGKrhRKPI0b .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jvGw7XGKrhRKPI0b .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jvGw7XGKrhRKPI0b .edgeLabel .label text{fill:#333;}#mermaid-svg-jvGw7XGKrhRKPI0b .label div .edgeLabel{color:#333;}#mermaid-svg-jvGw7XGKrhRKPI0b .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-jvGw7XGKrhRKPI0b .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-jvGw7XGKrhRKPI0b .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-jvGw7XGKrhRKPI0b .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-jvGw7XGKrhRKPI0b .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-jvGw7XGKrhRKPI0b .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jvGw7XGKrhRKPI0b .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jvGw7XGKrhRKPI0b #statediagram-barbEnd{fill:#333333;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jvGw7XGKrhRKPI0b .cluster-label,#mermaid-svg-jvGw7XGKrhRKPI0b .nodeLabel{color:#131300;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-jvGw7XGKrhRKPI0b .note-edge{stroke-dasharray:5;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-note text{fill:black;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram-note .nodeLabel{color:black;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagram .edgeLabel{color:red;}#mermaid-svg-jvGw7XGKrhRKPI0b #dependencyStart,#mermaid-svg-jvGw7XGKrhRKPI0b #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-jvGw7XGKrhRKPI0b .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jvGw7XGKrhRKPI0b :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

new Thread()

start()

等待 synchronized 锁

获取到锁

wait() / join()

sleep() / wait(time)

notify() / interrupt()

时间到 / interrupt()

run() 执行完毕

极少见,通常先变 RUNNABLE

极少见

极少见

NEW

RUNNABLE

BLOCKED

WAITING

TIMED_WAITING

TERMINATED

Untitled-2026-02-27-1528

线程生命周期核心规则:

  • 状态单向不可逆
    一旦线程调用 start() 进入 RUNNABLE,就永远回不到 NEW;一旦到达 TERMINATED,就再也无法进入任何其他状态(终态,不可复活)。

  • 同一个线程对象只能 start() 一次
    第二次调用 start() 会直接抛出 IllegalThreadStateException(一生只能启动一次)。

  • RUNNABLE 是“万能中转站”
    几乎所有状态转换都要经过 RUNNABLE(包括就绪+运行两种OS层面状态,JVM不细分);NEW → RUNNABLE → 各种阻塞/等待 → RUNNABLE → TERMINATED 是最典型路径。

  • 阻塞与等待的唤醒依赖外部事件

    • BLOCKED(synchronized锁竞争)→ 自动靠获得锁转为RUNNABLE
    • WAITING → 必须被 notify/notifyAll、unpark 或 被join的线程结束 唤醒
    • TIMED_WAITING → 除上述外,还可以靠时间到达自动唤醒
      程序员无法“强行把线程从等待中拽出来”,必须靠这些触发条件。
  • 禁止使用 stop()、suspend()、resume()
    这几个方法早在 JDK 1.2 就标记为Deprecated,极不安全:

    • stop() 会直接杀死线程,可能导致资源不释放、对象处于不一致状态
    • suspend() 会让线程永久挂起而不释放锁,极易死锁
      现代推荐做法:用 interrupt() + 主动检查中断标志(isInterrupted() / Thread.interrupted())来协作式终止线程。

    image-20260227153550076

  • interrupt() 只是“礼貌请求”中断,不是强制杀死

    • 仅对处于 sleep()、wait()、join()、park() 等可中断方法的线程会抛出 InterruptedException
    • 对普通运行代码无直接效果,必须由线程自己检查中断状态并主动退出
      (这是“优雅关闭线程”的核心原则)
  • run() 执行结束或未捕获异常 = 死亡
    线程的 TERMINATED 状态只能通过 run() 方法正常返回 或 抛出未捕获异常两种方式到达,没有其他途径。

  • 2 各状态详细说明

    总结:

    新建 → start() → 就绪 → 获取CPU → 运行
    运行 →

    • sleep/wait/join/park/synchronized拿不到锁 → 阻塞
    • yield()/时间片结束 → 就绪
    • run()结束/异常 → 终止

    阻塞 → 时间到/notify/unpark/锁释放 → 就绪

    (1)新建状态(New)

    • 特征:线程对象已被 new 创建,但还未调用 start() 方法。同一个线程对象不能多次调用 start () 方法,否则会抛出IllegalThreadStateException异常。

      image-20260227153433914

    • 此时线程:还没有被 JVM 分配资源(栈空间、程序计数器等),本质上只是一个普通 Java 对象。

    • 能做什么:只能调用 start(),不能调用 run()(直接调用 run() 只是普通方法,不会启动新线程)。

    • 代码示例:

    Thread t = new Thread(() -> {
    System.out.println("我正在运行");
    }); // ← 此时处于 New 状态

    状态流转:new Thread() → 新建 → t.start() → 就绪

    (2)就绪状态(Runnable / Ready)

    • 特征:已调用 start(),线程已经准备好运行,等待操作系统分配 CPU 时间片。
    • 注意:Java 官方 Thread.State 中把就绪 + 运行合并为一个 RUNNABLE 状态,但国内通常把它们拆开讲解。
    • 此时线程:在就绪队列中排队,具备运行的一切条件,只差 CPU。
    • 代码示例:

    t.start(); // ← 调用后立即进入就绪状态

    状态流转:

    • 就绪 → 获得 CPU → 运行
    • 运行中被抢占 / yield() / 时间片用完 → 回到 就绪

    (3)运行状态(Running)

    • 特征:线程已获得 CPU 时间片,正在真正执行 run() 方法中的代码。
    • 此时线程:是 CPU 的“宠儿”,正在跑业务逻辑。
    • 可能被打断的情况:
      • 时间片用完(最常见)
      • 调用 Thread.yield()(主动让出)
      • 被更高优先级线程抢占
      • 执行到阻塞操作(如 sleep、wait、synchronized 拿不到锁)

    状态流转:

    • 运行 → 执行完毕或异常 → 终止
    • 运行 → 遇到阻塞操作 → 阻塞

    (4)阻塞状态(Blocked / Waiting / Timed Waiting)

    这是面试最爱深挖的部分。阻塞不是一个单一状态,而是三大类:

    子状态英文触发方式(最常见)唤醒方式特点
    Blocked BLOCKED 竞争 synchronized 锁失败 其他线程释放锁 等待锁(monitor)
    Waiting WAITING obj.wait()、thread.join()、LockSupport.park() notify()/notifyAll()、unpark()、join线程结束 无限期等待
    Timed Waiting TIMED_WAITING Thread.sleep()、wait(timeout)、join(timeout)、parkNanos() 时间到 或 被提前唤醒 有超时时间

    代码示例(三大阻塞):

    // 1. BLOCKED(锁阻塞)
    synchronized (obj) {
    // 如果其他线程已经拿到锁,这里就会进入 BLOCKED
    }

    // 2. WAITING(无限等待)
    synchronized (obj) {
    obj.wait(); // 必须在 synchronized 中调用
    }

    // 3. TIMED_WAITING(限时等待)
    Thread.sleep(2000); // 最常见
    obj.wait(2000);
    t.join(5000);

    重要区别记忆口诀:

    • Blocked = 等锁(synchronized)
    • Waiting = 主动“喊暂停”(wait/park/join),需要别人叫醒
    • Timed Waiting = “喊暂停但带闹钟”(sleep/wait+timeout)

    状态流转:所有阻塞 → 条件满足 → 回到 就绪

    (5)终止状态(Terminated)

    • 特征:线程 run() 方法正常结束、抛出未捕获异常、或被 stop()(已废弃,不推荐)。
    • 此时线程:彻底死亡,资源被回收,不能再 start()(会抛 IllegalThreadStateException)。
    • 代码示例:

    // run() 执行完自动进入 Terminated
    // 或线程内抛出 RuntimeException 未捕获

    状态流转:不可逆!终止后无法回到任何其他状态。


    3 代码演示

    package Thread_Lifecycle;

    /**
    * 线程生命周期状态演示类
    * 展示Java线程的6种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
    */

    public class ThreadStateDemo {
    // 定义一个共享对象锁,用于演示线程同步和阻塞状态
    private static final Object lock = new Object();

    /**
    * 主方法 – 演示各种线程状态
    * @param args 命令行参数
    * @throws InterruptedException 当线程被中断时抛出
    */

    public static void main(String[] args) throws InterruptedException {
    // 1. NEW 状态演示
    // 创建线程对象但未调用start()方法,此时线程处于NEW状态
    Thread t1 = new Thread(() -> {
    // 线程执行体 – 实际工作代码
    System.out.println("t1 进入运行状态…");
    try {
    // 此时线程进入TIMED_WAITING状态
    Thread.sleep(200);
    } catch (InterruptedException e) {
    // 处理中断异常情况
    System.out.println("t1 被中断");
    }
    // 线程执行完毕,即将进入TERMINATED状态
    System.out.println("t1 执行结束 → TERMINATED");
    }, "t1"); // 给线程命名,便于识别和调试

    // 获取并打印线程创建后的初始状态(应该是NEW)
    System.out.println("t1 创建后状态: " + t1.getState());

    // 2. RUNNABLE状态演示
    // 调用start()方法启动线程,线程进入RUNNABLE状态(就绪态)
    // JVM调度器会很快将其分配CPU时间片开始执行
    t1.start();
    // 主线程休眠100毫秒,给t1线程时间开始执行
    Thread.sleep(100);
    // 此时t1应该已经在执行sleep()方法,处于TIMED_WAITING状态
    System.out.println("t1 start 后状态: " + t1.getState());

    // 3. BLOCKED状态演示(锁竞争场景)
    // 创建第一个线程t2,它会获取lock对象的监视器锁
    Thread t2 = new Thread(() -> {
    // 使用synchronized关键字获取lock对象的内置锁
    synchronized (lock) {
    System.out.println("t2 拿到锁,正在执行…");
    try {
    // 持有锁的情况下休眠0.3秒,期间其他线程无法获取该锁
    Thread.sleep(300);
    } catch (InterruptedException ignored) {
    // 忽略中断异常
    }
    }
    // synchronized块结束时自动释放锁
    }, "t2");

    // 创建第二个线程t3,它也会尝试获取同一个lock对象的锁
    Thread t3 = new Thread(() -> {
    // 当t2持有锁时,t3执行到这里会被阻塞
    // 因为无法获取已被t2占用的锁,进入BLOCKED状态
    synchronized (lock) {
    System.out.println("t3 拿到锁");
    }
    }, "t3");

    // 启动t2线程,让它先获取锁
    t2.start();
    // 等待200毫秒确保t2已经获取到锁
    Thread.sleep(200);
    // 启动t3线程,此时t3会因为锁被占用而进入BLOCKED状态
    t3.start();
    // 等待300毫秒让t3充分体验BLOCKED状态
    Thread.sleep(300);
    // 打印t3的状态,应该显示为BLOCKED
    System.out.println("t3 状态(应为 BLOCKED): " + t3.getState());

    // 4. WAITING状态演示(使用Object.wait()方法)
    // 创建t4线程用于演示无限期等待状态
    Thread t4 = new Thread(() -> {
    // 获取lock对象的锁
    synchronized (lock) {
    try {
    System.out.println("t4 进入 wait → WAITING");
    // 调用wait()方法释放锁并进入无限期等待状态
    // 直到其他线程调用notify()/notifyAll()才会唤醒
    lock.wait();
    } catch (InterruptedException e) {
    // 处理可能的中断异常
    e.printStackTrace();
    }
    }
    }, "t4");

    // 启动t4线程
    t4.start();
    // 等待500毫秒确保t4进入WAITING状态
    Thread.sleep(500);
    // 打印t4状态,应该显示为WAITING
    System.out.println("t4 状态(应为 WAITING): " + t4.getState());

    // 唤醒处于WAITING状态的t4线程
    // 需要先获取相同的锁对象才能调用notify()
    synchronized (lock) {
    // 唤醒在lock对象上等待的单个线程(t4)
    lock.notify();
    }

    // 5. TIMED_WAITING状态演示(使用带超时的join方法)
    // 创建t5线程用于演示定时等待
    Thread t5 = new Thread(() -> {
    try {
    // t5线程简单地休眠0.5秒
    Thread.sleep(500);
    } catch (InterruptedException ignored) {
    // 忽略中断异常
    }
    }, "t5");
    // 启动t5线程
    t5.start();

    // 获取当前主线程的引用
    Thread main = Thread.currentThread();
    // 创建一个辅助线程来演示主线程的TIMED_WAITING状态
    new Thread(() -> {
    try {
    // 调用t5.join(2000)使当前线程(辅助线程)等待t5线程最多0.2秒
    // 如果2秒内t5没有结束,则继续执行
    // 调用线程在此期间进入TIMED_WAITING状态
    t5.join(500);
    } catch (InterruptedException e) {
    // 处理中断异常
    e.printStackTrace();
    }
    }).start();

    // 等待500毫秒确保辅助线程已经开始等待
    Thread.sleep(500);
    // 打印主线程状态,应该显示为TIMED_WAITING
    System.out.println("主线程在 join(2000) 时状态: " + main.getState());

    // 等待所有演示线程完成执行
    // join()方法使当前线程(main线程)等待指定线程执行完毕
    t1.join();
    t2.join();
    t3.join();
    t4.join();
    t5.join();
    // 打印t1线程的最终状态,应该是TERMINATED
    System.out.println("t1 最终状态: " + t1.getState());
    }
    }

    SNAP_2026-02-27_16-47-57

    4 wait() 和 sleep() 的 8 大区别(面试必问)

    口诀总结:“wait会放锁睡大觉,别人叫醒才起床;sleep抱锁睡小觉,时间一到自己醒。”

    序号比较项wait()sleep()记忆口诀
    1 所属类 Object Thread wait是对象的,sleep是线程的
    2 使用环境 必须在 synchronized 块/方法内 无需 synchronized wait必须“有锁”
    3 是否释放锁 释放当前持有的锁 不释放锁 wait会放锁,sleep死抓着
    4 唤醒方式 notify/notifyAll 或 interrupt 时间到自动醒,或 interrupt wait靠别人,sleep靠闹钟
    5 是否可超时 有重载 wait(long timeout) 有 sleep(long millis) 两者都可带时间
    6 中断响应 抛 InterruptedException 并清除中断标志 抛 InterruptedException 并清除中断标志 行为一致
    7 所属状态(最典型) WAITING 或 TIMED_WAITING TIMED_WAITING sleep一定是限时等待
    8 假唤醒(spurious wakeup) 可能发生,必须放在 while 循环中判断条件 不存在假唤醒 wait要防“骗醒”

    5 Thread.State 枚举源码分析

    理解线程状态流转对于排查死锁和性能问题至关重要。Java 线程主要有以下 6 种状态(基于 Thread.State 枚举):

  • NEW (新建):创建了线程对象,但未调用 start()。
  • RUNNABLE (可运行):调用了 start(),正在 JVM 中等待 CPU 时间片,或者正在运行中。
  • BLOCKED (阻塞):等待获取监视器锁(synchronized 锁)。
  • WAITING (无限等待):调用 wait(), join(), LockSupport.park(),需被其他线程唤醒。
  • TIMED_WAITING (计时等待):调用 sleep(time), wait(time),时间到了自动唤醒。
  • TERMINATED (终止):线程执行结束。
  • public class Thread implements Runnable {
    public enum State {
    /**线程尚未启动。还未调用 start()。*/
    NEW,

    /**线程在 JVM 中执行中(包括就绪 + 真正运行 + OS 调度相关等待)。
    * 这是最宽泛的状态。*/

    RUNNABLE,

    /** 线程在等待 monitor 锁(synchronized 块/方法)。
    * 典型场景:竞争 synchronized 锁失败。*/

    BLOCKED,

    /** 线程在无限期等待另一个线程执行特定动作。
    * 典型:wait()、join()、LockSupport.park()*/

    WAITING,

    /** 线程在有限时间内等待另一个线程执行特定动作。
    * 典型:sleep()、wait(timeout)、join(timeout)、parkNanos、parkUntil*/

    TIMED_WAITING,

    /**线程已终止(run()正常结束或异常结束)。
    * 不可再 start()。*/

    TERMINATED;
    }
    }

    image-20260227165355165

    6 Java线程状态与操作系统内核线程的对应关系

    Java 线程状态操作系统层面(典型对应)说明
    NEW 无(尚未创建内核线程) Java 层只是对象,start() 后才真正创建 pthread / kernel thread
    RUNNABLE Ready / Running 就绪队列中等待调度 或 正在 CPU 上执行
    BLOCKED Waiting (for mutex / monitor) 等待互斥锁(synchronized 底层是 monitorenter)
    WAITING Waiting / Suspended / Parked 等待条件变量(wait/notify 底层是条件变量)、futex wait、park 等
    TIMED_WAITING Waiting with timeout 同上,但设置了超时(sleep、wait(timeout)、pthread_cond_timedwait 等)
    TERMINATED Zombie → Dead 线程结束,等待被 join 或系统回收资源

    总结对应规律:

    • Java 故意简化了状态(RUNNABLE 合并就绪+运行),隐藏了操作系统细节

    • BLOCKED 是最“重”的阻塞(与锁相关),其他都是“轻量级”等待

    • 现代 JVM(HotSpot)底层大量使用 park/unpark(基于 futex / semaphore 等),而不是传统条件变量

      Grok给出:

      image-20260228120710977image-20260228120744125

    image-20260228113610377

    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.LockSupport;
    import java.util.concurrent.locks.ReentrantLock;

    public class ThreadStateDemo {

    private static final ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) throws Exception {
    // 1. NEW 状态(创建但未start)
    Thread tNew = new Thread(() -> {}, "t-new");
    printThreadInfo(tNew, "刚new出来");

    // 2. RUNNABLE(正在计算或ready)
    Thread tRunnable = new Thread(() -> {
    long start = System.currentTimeMillis();
    while (true) {
    if (System.currentTimeMillis() start > 20_000) break;
    Math.sin(Math.random()); // 占用CPU
    }
    }, "t-runnable");
    tRunnable.start();
    Thread.sleep(800); // 让它跑起来
    printThreadInfo(tRunnable, "RUNNABLE – 忙循环");

    // 3. BLOCKED(synchronized争锁)
    Thread tBlocked = new Thread(() -> {
    synchronized (ThreadStateDemo.class) {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(30));
    }
    }, "t-blocked");

    // 先让主线程持有锁
    synchronized (ThreadStateDemo.class) {
    tBlocked.start();
    Thread.sleep(800);
    printThreadInfo(tBlocked, "BLOCKED – 争synchronized锁");
    }

    // 4. WAITING(Object.wait() 无超时)
    Thread tWaiting = new Thread(() -> {
    synchronized (ThreadStateDemo.class) {
    try {
    ThreadStateDemo.class.wait(); // 会一直等
    } catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    }
    }
    }, "t-waiting");
    tWaiting.start();
    Thread.sleep(800);
    printThreadInfo(tWaiting, "WAITING – Object.wait()");

    // 5. TIMED_WAITING(几种常见形式)
    Thread tTimed = new Thread(() -> {
    try {
    Thread.sleep(15000); // 最简单的一种
    // 或者: LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(30));
    // 或者: synchronized后 wait(15000)
    } catch (Exception e) {
    Thread.currentThread().interrupt();
    }
    }, "t-timed-waiting");
    tTimed.start();
    Thread.sleep(800);
    printThreadInfo(tTimed, "TIMED_WAITING – Thread.sleep()");

    // 6. 让程序不要马上退出
    System.out.println("\\n所有演示线程已启动。pid = " + ProcessHandle.current().pid());
    System.out.println("请在新终端运行以下命令观察(大约10秒内):");
    System.out.println(" jstack " + ProcessHandle.current().pid());
    System.out.println(" top -H -p " + ProcessHandle.current().pid());
    System.out.println(" ps -eLo pid,lwp,stat,comm | grep t-");
    System.out.println(" cat /proc/" + ProcessHandle.current().pid() + "/task/[LWP]/stat # 看第3列状态字母");
    System.out.println("\\n按回车退出…");
    System.in.read();
    }

    private static void printThreadInfo(Thread t, String msg) {
    System.out.printf("%-25s : %-10s (java state)%n", msg, t.getState());
    }
    }

    image-20260228112014228

    SNAP_2026-02-28_11-57-12

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Java | 线程 - 生命周期
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!