一句话说透Java里面的线程的生命周期

131 阅读2分钟

Java线程的生命周期就像  “人的一天” ,从出生到结束,经历不同状态。线程共有 6种状态(定义在 Thread.State 枚举中),核心流程如下:


1. 新建状态(NEW)  →  “刚出生”

  • 触发条件:线程对象被创建(new Thread()),但还没调用 start()

  • 特点:还没开始工作,只是个空壳。

    java

    复制

    Thread thread = new Thread(() -> System.out.println("干活!"));  
    System.out.println(thread.getState()); // 输出:NEW  
    

2. 可运行状态(RUNNABLE)  →  “准备好跑步”

  • 触发条件:调用 start() 方法后,线程进入就绪队列,等待CPU分配时间片。

  • 特点

    • 可能在运行(CPU时间片到手),也可能在排队等CPU(就绪)。

    • 这是线程的“活跃状态”,要么正在干活,要么随时能干活。

    thread.start();  
    System.out.println(thread.getState()); // 输出:RUNNABLE  
    

3. 阻塞状态(BLOCKED)  →  “堵在门口等钥匙”

  • 触发条件:线程试图获取某个对象的锁(如 synchronized 代码块),但锁被其他线程占用。

  • 例子

    • 线程A进厕所锁门了,线程B只能在门外干等。

    synchronized (lock) {  
        // 线程A拿到锁,线程B在锁外等待 → BLOCKED  
    }  
    

4. 无限等待状态(WAITING)  →  “等朋友来叫”

  • 触发条件:线程主动调用以下方法,释放锁并进入等待:

    • object.wait():等别人通知(notify())。
    • thread.join():等另一个线程结束。
  • 特点:一直等,直到被明确唤醒。

    synchronized (lock) {  
        lock.wait(); // 进入WAITING状态  
    }  
    

5. 超时等待状态(TIMED_WAITING)  →  “等,但有闹钟”

  • 触发条件:调用带超时参数的方法:

    • Thread.sleep(时间)
    • object.wait(超时时间)
    • thread.join(超时时间)
  • 特点:等一段时间后自动醒,或中途被唤醒。

    Thread.sleep(1000); // 睡1秒 → TIMED_WAITING  
    

6. 终止状态(TERMINATED)  →  “下班了”

  • 触发条件:线程的 run() 方法执行完毕,或异常终止。

  • 特点:线程彻底结束,无法重启(调用 start() 会抛异常)。

    thread.start();  
    thread.join(); // 等线程结束  
    System.out.println(thread.getState()); // 输出:TERMINATED  
    

生命周期流程图

      NEW  
       ↓  
   start()  
       ↓  
  RUNNABLE ←──────┐  
       |          阻塞(抢锁失败)  
       |           ↓  
       |       BLOCKED  
       |  
       |── wait()/join() → WAITING  
       |  
       |── sleep(ms)/wait(ms) → TIMED_WAITING  
       ↓  
  TERMINATED

关键区别总结

状态触发条件能否自动恢复
BLOCKED抢不到锁锁释放后自动竞争
WAITING调用 wait()/join()必须等 notify()/join完成
TIMED_WAITING调用带超时的方法(如 sleep(1000)时间到或中途被唤醒

常见问题

  1. 线程卡在 RUNNABLE 但没执行?

    • 正常现象,说明线程在就绪队列等待CPU时间片。
  2. WAITING 和 BLOCKED 的区别?

    • BLOCKED 是抢不到锁被堵住,WAITING 是主动释放锁并等待通知。
  3. 如何避免线程永久阻塞?

    • 用 TIMED_WAITING 替代 WAITING,设置超时时间。

口诀
「线程一生六状态,新建就绪阻塞等
抢锁失败会阻塞,主动等待需人叫
超时等待设闹钟,任务完成就下班!」