【Java多线程与高并发系列】第3讲:线程的生命周期与状态转换

141 阅读3分钟

🧠 一、Java 线程的六大状态(Thread.State)

Java线程在运行过程中会不断经历状态变化,JVM通过 Thread.State​ 枚举定义了六种状态:

状态名含义典型触发方式
NEW新建状态,线程对象已创建但未启动​new Thread()​
RUNNABLE就绪或运行中(取决于CPU调度)调用start()​
BLOCKED阻塞等待锁(Monitor)​synchronized​获取锁失败
WAITING无限期等待被唤醒​Object.wait()​、LockSupport.park()​
TIMED_WAITING有时限等待​Thread.sleep()​、join(timeout)​、wait(timeout)​
TERMINATED线程执行完毕或异常退出run() 执行结束

📘 ​注意​:
Java 的 “RUNNABLE” 状态实际上包含两种:​Running​(运行中)和 ​Ready​(可运行但等待 CPU 时间片)。
真正的调度权在 操作系统内核调度器 手中。


🔑 二、关键方法与状态变化

1️⃣ 启动阶段:start()​ 与 run()​

Thread t = new Thread(() -> {
    System.out.println("Running...");
});
System.out.println(t.getState()); // NEW
t.start();
System.out.println(t.getState()); // RUNNABLE
  • ​start()​ 会向 JVM 注册一个新的系统线程,最终由 操作系统内核 创建。
  • ​run()​ 只是普通方法调用,不会启动新线程。
  • 调用完 start()​ 后,线程进入 RUNNABLE 状态,等待调度执行。

2️⃣ 等待与唤醒机制:wait() / notify() / notifyAll()​

Object lock = new Object();

Thread t = new Thread(() -> {
    synchronized (lock) {
        try {
            System.out.println("等待中...");
            lock.wait(); // 进入 WAITING 状态
            System.out.println("被唤醒,继续执行");
        } catch (InterruptedException e) {}
    }
});

t.start();
Thread.sleep(1000);

synchronized (lock) {
    lock.notify(); // 唤醒一个等待线程
}
  • ​wait()​ 会 释放锁 并进入 WAITING。
  • ​notify()​ 唤醒一个线程(不保证立刻执行,需重新竞争锁)。
  • ​notifyAll()​ 唤醒所有等待该锁的线程。

⚠️ wait()​、notify()​ 必须在同步块内调用,否则抛出 IllegalMonitorStateException​。


3️⃣ 定时等待:sleep()​ 与 join(timeout)​

Thread t = new Thread(() -> {
    try {
        System.out.println("Sleeping...");
        Thread.sleep(3000); // TIMED_WAITING
    } catch (InterruptedException e) {}
});
t.start();
  • ​sleep()​ 不释放锁,当前线程进入 ​TIMED_WAITING​。
  • ​join(timeout)​ 使调用方线程等待目标线程结束,超时后恢复运行。

4️⃣ 挂起与唤醒:LockSupport.park()​ / unpark()​

import java.util.concurrent.locks.LockSupport;

Thread t = new Thread(() -> {
    System.out.println("线程开始,进入等待");
    LockSupport.park();  // WAITING
    System.out.println("被唤醒继续执行");
});
t.start();

Thread.sleep(2000);
LockSupport.unpark(t); // 唤醒线程
  • ​park()​ 会挂起当前线程,不释放锁。
  • ​unpark(Thread)​ 唤醒指定线程。
  • 这一机制底层基于 ​Unsafe.park()​,是JUC(如Semaphore​、ReentrantLock​)的基础。

5️⃣ 阻塞等待锁:synchronized​ 与 BLOCKED​

Object lock = new Object();

Thread t1 = new Thread(() -> {
    synchronized (lock) {
        try { Thread.sleep(5000); } catch (InterruptedException e) {}
    }
}, "LockHolder");

Thread t2 = new Thread(() -> {
    synchronized (lock) { System.out.println("获得锁"); }
}, "BlockedThread");

t1.start();
Thread.sleep(100); // 确保t1先拿到锁
t2.start();

此时:

  • ​t1​ 正在 sleep()​ → TIMED_WAITING​
  • ​t2​ 尝试进入 synchronized​ → BLOCKED​

💡 BLOCKED​ 状态不响应中断,只有锁释放后才能恢复为 RUNNABLE​。


6️⃣ 终止:线程自然结束或异常退出

当 run()​ 执行完毕,线程进入 TERMINATED​ 状态。
此时无法再次调用 start()​,否则抛出 IllegalThreadStateException​。


🧩 三、线程状态的综合演示

我们来写一个综合示例来观察线程的不同状态:

public class ThreadStateDemo {
    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(5000); // TIMED_WAITING
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "SleepThread");

        Thread t2 = new Thread(() -> {
            synchronized (ThreadStateDemo.class) {
                try { Thread.sleep(5000); } catch (InterruptedException e) {}
            }
        }, "LockThread");

        Thread t3 = new Thread(() -> {
            synchronized (ThreadStateDemo.class) {
                System.out.println("Hold lock");
            }
        }, "BlockedThread");

        t1.start();
        t2.start();
        Thread.sleep(100);
        t3.start();

        // 持续打印线程状态
        for (int i = 0; i < 6; i++) {
            System.out.printf("%s: %s%n", t1.getName(), t1.getState());
            System.out.printf("%s: %s%n", t2.getName(), t2.getState());
            System.out.printf("%s: %s%n", t3.getName(), t3.getState());
            Thread.sleep(1000);
        }
    }
}

运行时输出示例:

SleepThread: TIMED_WAITING
LockThread: TIMED_WAITING
BlockedThread: BLOCKED
SleepThread: TIMED_WAITING
LockThread: TIMED_WAITING
BlockedThread: BLOCKED
SleepThread: TIMED_WAITING
LockThread: TIMED_WAITING
BlockedThread: BLOCKED
SleepThread: TIMED_WAITING
LockThread: TIMED_WAITING
BlockedThread: BLOCKED
SleepThread: TIMED_WAITING
LockThread: TIMED_WAITING
BlockedThread: BLOCKED
Hold lock
SleepThread: TERMINATED
LockThread: TERMINATED
BlockedThread: TERMINATED