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


(待更新)

相关推荐
Hello小赵2 小时前
C语言如何自定义链接库——编译与调用
android·java·c语言
John.Lewis2 小时前
C++进阶(8)智能指针
开发语言·c++·笔记
希望永不加班2 小时前
SpringBoot 配置绑定:@ConfigurationProperties
java·spring boot·后端·spring
悟空码字2 小时前
MySQL性能优化的天花板:10条你必须掌握的顶级SQL分析技巧
java·后端·mysql
indexsunny2 小时前
互联网大厂Java面试实战:Spring Boot、MyBatis与Kafka在电商场景中的应用
java·spring boot·面试·kafka·mybatis·电商·技术栈
殷紫川2 小时前
CompletableFuture 异步编程全解:核心能力、编排方案、异常处理与超时控制
java
CoderCodingNo2 小时前
【GESP】C++二级真题 luogu-B4497, [GESP202603 二级] 数数
开发语言·c++·算法
ss2732 小时前
致Java初学者的一封信
java·开发语言
white-persist2 小时前
【vulhub spring CVE-2018-1270】CVE-2018-1270 Spring Messaging 远程命令执行漏洞 完整复现详细分析解释
java·服务器·网络·数据库·后端·python·spring