Skip to content
清晨的一缕阳光
返回

Java 线程状态详解

Java 线程状态详解

Java 线程的六种状态描述了线程从创建到终止的完整生命周期,理解状态转换是掌握多线程的基础。

一、六种线程状态

public enum State {
    NEW,              // 新建
    RUNNABLE,         // 运行
    BLOCKED,          // 阻塞
    WAITING,          // 等待
    TIMED_WAITING,    // 超时等待
    TERMINATED        // 终止
}

状态转换图

image-20250727163213257


二、状态详解

2.1 NEW(新建状态)

线程对象已创建,但尚未调用 start() 方法:

Thread thread = new Thread(() -> {
    System.out.println("Running");
});
// 此时 thread.getState() == State.NEW

2.2 RUNNABLE(运行状态)

包含两种情况:

thread.start();
// 此时 thread.getState() == State.RUNNABLE

2.3 BLOCKED(阻塞状态)

线程因竞争同步锁失败而暂停:

// 线程 A 持有锁
synchronized (lock) {
    // 线程 B 尝试获取锁 → BLOCKED
}

转换条件

2.4 WAITING(等待状态)

无限期等待,需其他线程显式唤醒:

// 方式 1:Object.wait()
synchronized (obj) {
    obj.wait();
}

// 方式 2:Thread.join()
thread.join();

// 方式 3:LockSupport.park()
LockSupport.park();

唤醒方式

2.5 TIMED_WAITING(超时等待)

有限期等待,超时后自动唤醒:

// 方式 1:Thread.sleep(time)
Thread.sleep(1000);

// 方式 2:Object.wait(time)
synchronized (obj) {
    obj.wait(1000);
}

// 方式 3:Thread.join(time)
thread.join(1000);

// 方式 4:LockSupport.parkNanos(time)
LockSupport.parkNanos(1000_000_000L);

2.6 TERMINATED(终止状态)

线程执行完毕或因异常退出:

thread.run(); // 执行完毕
// 此时 thread.getState() == State.TERMINATED

三、状态转换实战

3.1 BLOCKED → RUNNABLE

Object lock = new Object();

// 线程 A
new Thread(() -> {
    synchronized (lock) {
        Thread.sleep(2000); // 持有锁 2 秒
    }
}).start();

// 线程 B
new Thread(() -> {
    synchronized (lock) { // 竞争锁失败 → BLOCKED
        System.out.println("Got lock"); // 获取锁 → RUNNABLE
    }
}).start();

3.2 yield() vs sleep()

方法作用状态变化锁释放
yield()让出 CPU 时间片RUNNABLE → RUNNABLE不释放
sleep()暂停指定时间RUNNABLE → TIMED_WAITING不释放
// yield() - 让出 CPU,但仍可被调度
Thread.yield();

// sleep() - 暂停 1 秒
Thread.sleep(1000);

四、常见问题

4.1 如何查看线程状态?

Thread thread = new Thread(() -> {
    // ...
});

// 方式 1:getState()
System.out.println(thread.getState());

// 方式 2:jstack(命令行)
jstack <pid>

// 方式 3:VisualVM(图形化)

4.2 死锁检测

// 死锁:两个线程互相等待对方的锁
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] deadlockedThreads = bean.findDeadlockedThreads();

if (deadlockedThreads != null) {
    System.out.println("检测到死锁!");
}

4.3 如何避免死锁?

  1. 固定顺序:所有线程按相同顺序获取锁
  2. 超时机制:使用 tryLock(timeout)
  3. 死锁检测:定期检测并恢复

五、总结

线程状态核心要点:

状态触发条件唤醒方式
NEW创建线程对象start()
RUNNABLE就绪/运行中CPU 调度
BLOCKED竞争锁失败获取锁
WAITINGwait()/join()/park()notify()/unpark()
TIMED_WAITINGsleep()/wait(time)超时/唤醒
TERMINATEDrun() 结束-

理解线程状态转换是解决并发问题的基础,建议结合 jstack 等工具实际观察。


分享这篇文章到:

上一篇文章
synchronized 底层原理详解
下一篇文章
HashMap 底层原理详解