在 Java 中,每个线程都有它的“人生轨迹”,它会经历6 种状态,而这些状态会影响线程的运行、调度和资源占用情况。

Thread.State 规定 Java线程的六种状态:

1
2
3
4
5
6
7
8
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}

New

1
2
Thread t = new Thread(() -> {});
// 还没 start(),状态为 NEW

线程被创建但还未启动,只有调用start()才会进入下一个状态

RUNNABLE(可运行)

1
2
3
4
Thread t = new Thread(() -> {
while (true) {} // 占用CPU
});
t.start(); // 进入 RUNNABLE 状态

线程可以运行,正在被调度或等待 CPU 时间片,不代表一定正在执行,只是“有资格执行”。

BLOCKED(阻塞)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class BlockDemo {
static final Object lock = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (lock) {
while (true) {}
}
}).start();

new Thread(() -> {
synchronized (lock) {
System.out.println("永远进不来");
}
}).start();
}
}

第二个线程在等待锁的释放(进入同步块的时候被其他线程占用)

WAITING(无限等待)

1
2
3
4
5
6
7
8
9
Object lock = new Object();
Thread t = new Thread(() -> {
synchronized (lock) {
try {
lock.wait(); // 永久等待,直到被唤醒
} catch (InterruptedException e) {}
}
});
t.start();

只有另一个线程调用lock.notify()notifyAll()才会被唤醒,用于线程之间的通信

TIMED_WAITING(超时等待)

1
2
3
4
Thread.sleep(1000);            // 休眠1秒
object.wait(500); // 等待0.5秒
thread.join(1000); // 等待别的线程最多1秒
lock.tryLock(1, TimeUnit.SECONDS); // 带超时的获取锁

等待指定时间后自动唤醒

TERMINATED(终止)

1
2
3
4
Thread t = new Thread(() -> System.out.println("结束"));
t.start();
t.join(); // 等线程执行完
System.out.println(t.getState()); // TERMINATED

正常执行完、抛出异常后使得线程已经结束,不再参与调度。

状态切换图示