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


(待更新)

相关推荐
文丑颜不良啊2 小时前
LeetCode2761~2780题目解析
java·leetcode
IT枫斗者枫哥2 小时前
子线程断言失败,JUnit 为什么还显示通过?
java·后端
码农小河664 小时前
基于PHP的电商后台蜜罐系统
开发语言·php
starzy19904 小时前
深入理解Scala柯里化函数:函数链式变换
开发语言·scala
ShineWinsu4 小时前
对于Qt:QTreeWidget常见属性以及QTreeWidgetItem类的解析
开发语言·c++·qt·gui·客户端·多叉树·qtreewidget
落羽的落羽5 小时前
【C++】C++17的主要特性
linux·服务器·开发语言·c++·算法·机器学习
考虑考虑5 小时前
JDK27中的Set.ofLazy
java·后端·java ee
文丑颜不良啊5 小时前
LeetCode2841~2860题目解析
java·leetcode
小南家的青蛙5 小时前
Tomcat与Jetty深度对比
java·tomcat·jetty
总要学点什么5 小时前
第108篇:三维特效-图片轨迹线效果——把贴图滚成一串箭头,想用它的本色反而整条消失
开发语言·javascript·ecmascript·gis·webgl·材质·cesium