🧠 一、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