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


(待更新)

相关推荐
http阿拉丁神猫3 小时前
Go语言入门笔记:从基础到开发环境搭建(二)
开发语言·笔记·golang
不会就选b3 小时前
C++补充部分(一)--lambda 表达式
开发语言·c++
Pniubi6 小时前
HashMap的扩容和树化边界
java·开发语言
Mikko77 小时前
用 Java 复刻了高中时在塞班上玩的「熔岩矿车」:纯 Swing、零依赖、没有一张图片,一个 jar 双击就能玩
java·游戏开发·swing
知了学历孙老师7 小时前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
Java爱好狂.7 小时前
Java初学者如何一周速通SpringBoot!
java·spring boot·后端·spring·高并发·架构师·java面试
秋饼8 小时前
LLM API密钥动态轮换实战:Spring Vault + Spring AI + 多Provider路由
java·ai·技术分享·后端开发
gCode Teacher 格码致知8 小时前
Pandas教学-17:Series与Dataframe的关系
开发语言·python·pandas
发量惊人的中年网工8 小时前
分公司访问总部ERP慢怎么办?SD-WAN组网的排查与验收要点
服务器·开发语言·php
下页、再停留8 小时前
【C#桌面客户端系列学习-15】生成可视化图表之折线图、柱状图、饼状图
开发语言·c#