【JAVA基础面经】线程的状态
线程的基本状态
通过t.getState()方法获取对应线程的状态
- NEW状态:安排了工作还未开始行动,即Thread对象创建了但是还没有调用start()方法
- TERMINATED状态:工作完成了,操作系统中的线程已经执行完毕销毁了,但是Thread对象还在,从而获取到的状态
- RUNNABLE状态:可工作的,又可以分为正在工作中和即将开始工作的,也是就绪状态,处于该状态的线程在就绪队列中,随时可以被调用到CPU上执行。如果代码中没有进行sleep或其他可能导致阻塞的操作,线程即在RUNNABLE状态
- TIMED_WAITING状态:代码中调用了 sleep 或 join 等操作就会进入到该状态,即当前线程在一定时间内是阻塞的状态,一定时间后状态解除
- BLOCKED状态:当前线程在等待锁导致了阻塞
- WAITING状态:当前线程在等待唤醒导致了阻塞
线程的状态转移

在 JVM 层面,RUNNABLE该状态包括:就绪(ready)和运行中(running)。线程可能在等待 CPU 时间片,也可能正在执行,他们都属于RUNNABLE状态
Thread类的属性和方法
构造方法
给线程起名字方便再调试的时候对线程进程区分,可以借助JDK中的jconsole观察线程的名字
| 方法 | 说明 |
|---|---|
| public Thread() | 创建线程对象 |
| public Thread(Runnable target) | 使用Runnable对象创建线程对象 |
| public Thread(String name) | 创建线程对象,并命名 |
| public Thread(Runnable target, String name) | 使用Runnable对象创建线程对象,并命名 |
属性
| 属性 | 获取方法 |
|---|---|
| ID | getId() |
| 名称 | getName() |
| 状态 | getState() |
| 优先级 | getPriority() |
| 是否后台线程 | isDaemon() |
| 是否存活 | isAlive() |
| 是否被中断 | isInterrupted() |
- 是否后台线程 isDaemon():JVM会在一个进程的所有非后台线程结束之后才会结束执行。如果线程是后台线程,那么就不影响进程的推出,如果是前台线程,就会影响到进程的进出
- 是否存活 isAlive():指操作系统中对应的线程是否正在运行,Thread t 只是创建了一个对象,创建 t 对象后调用t.start()才是创建了一个线程,因此t对象的生命周期和内核中线程对应的生命周期并不完全一致,run方法执行完毕后系统中的线程就销毁了,但是t对象可能还存在。start()开始之后,run()结束之前的时间内isAlive()判定为true
各状态详细说明
NEW(新建)
线程对象已创建,但未调用 start(),此时线程尚未与操作系统线程关联。
java
Thread t = new Thread(() -> System.out.println("hello"));
System.out.println(t.getState()); // NEW
RUNNABLE(可运行)
调用 start() 后,线程进入 RUNNABLE 状态。在 JVM 层面,该状态包括:就绪(ready)和运行中(running)。线程可能在等待 CPU 时间片,也可能正在执行。即使线程在执行 sleep 或 wait 之前的代码,也属于 RUNNABLE(未阻塞时)
java
Thread t = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
});
t.start();
System.out.println(t.getState()); // RUNNABLE(很可能)
BLOCKED(阻塞)
线程在等待获取一个 synchronized 锁时,会进入 BLOCKED 状态
Lock 接口(如 ReentrantLock)导致的等待不会进入 BLOCKED,而是 WAITING 或 TIMED_WAITING(因为 LockSupport.park())
java
public class BlockedDemo {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
synchronized (lock) {
try { Thread.sleep(10000); } catch (InterruptedException e) {}
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) {
System.out.println("获得到锁");
}
});
t1.start();
Thread.sleep(100); // 确保 t1 先获得锁
t2.start();
Thread.sleep(100);
System.out.println(t2.getState()); // BLOCKED
}
}
WAITING(无限等待)
线程进入等待状态,直到其他线程执行特定操作唤醒它,常见进入方式包括:
- Object.wait()(无超时)
- Thread.join()(无超时)
- LockSupport.park()
唤醒方式包括:
- Object.notify() / notifyAll()
- join() 的线程执行完毕
- LockSupport.unpark(thread)
java
public class WaitingDemo {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread t = new Thread(() -> {
synchronized (lock) {
try { lock.wait(); } catch (InterruptedException e) {}
}
});
t.start();
Thread.sleep(100); // 确保 t 进入 wait
System.out.println(t.getState()); // WAITING
}
}
TIMED_WAITING(限期等待)
与 WAITING 类似,但指定了超时时间,时间到自动返回。常见进入方式包括:
- Thread.sleep(long millis)
- Object.wait(long timeout)
- Thread.join(long millis)
- LockSupport.parkNanos()
java
Thread t = new Thread(() -> {
try { Thread.sleep(5000); } catch (InterruptedException e) {}
});
t.start();
Thread.sleep(100);
System.out.println(t.getState()); // TIMED_WAITING
TERMINATED(终止)
线程 run() 方法执行完毕,或者因未捕获异常而结束。线程一旦终止,不能再次 start()(会抛出 IllegalThreadStateException)。
java
Thread t = new Thread(() -> {});
t.start();
t.join(); // 等待结束
System.out.println(t.getState()); // TERMINATED
线程中断
线程休眠
常见面试题
1.sleep() 和 wait() 的区别?
| 区别 | sleep() | wait() |
|---|---|---|
| 所属 | Thread 类的静态方法 | Object 类的实例方法 |
| 是否释放锁 | 不释放 | 释放 |
| 唤醒方式 | 时间到自动醒,或 interrupt() | 需要 notify()/notifyAll() 或超时 |
| 使用要求 | 任何地方 | 必须在 synchronized 块/方法内 |
2.BLOCKED 和 WAITING 有什么区别?
- BLOCKED 是在等待 synchronized 锁,是被动的、由 JVM 管理。
- WAITING 是主动调用 wait()、join() 等方法进入,等待其他线程显式唤醒,通常与锁配合(wait 必须持有锁)。
3.线程终止后能否再次启动?
不能。start() 方法只能调用一次,再次调用会抛出 IllegalThreadStateException。
3.notify 和 notifyAll 的区别?
(待更新)