【JAVA基础面经】线程的状态

【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 的区别?


(待更新)

相关推荐
老了,不知天命9 小时前
鳶尾花項目JAVA
java·开发语言·机器学习
BIGmustang9 小时前
python练手之用tkinter写一个计算器
开发语言·python
二哈赛车手10 小时前
新人笔记---实现简易版的rag的bm25检索(利用ES),以及RAG上传时的ES与向量数据库双写
java·数据库·笔记·spring·elasticsearch·ai
winner888110 小时前
从零吃透C++命名空间、std、#include、string、vector
java·开发语言·c++
AI人工智能+电脑小能手10 小时前
【大白话说Java面试题】【Java基础篇】第26题:Java的抽象类和接口有哪些区别
java·开发语言·面试
bzmK1DTbd10 小时前
SOLID原则在Java中的实践:单一职责与开闭原则
java·开发语言·开闭原则
AI进化营-智能译站10 小时前
ROS2 C++开发系列07-高效构建机器人决策逻辑,运算符与控制流实战
开发语言·c++·ai·机器人
winner888110 小时前
C++ 命名空间、虚函数、抽象类、protected 权限全套通俗易懂精讲(附与 Java 对比)
java·开发语言·c++
不会编程的懒洋洋10 小时前
C# P/Invoke 基础
开发语言·c++·笔记·安全·机器学习·c#·p/invoke
直奔標竿10 小时前
Java开发者AI转型第二十五课!Spring AI 个人知识库实战(四)——RAG来源追溯落地,拒绝AI幻觉
java·开发语言·人工智能·spring boot·后端·spring