Java线程状态
外观
Java线程状态是理解多线程编程的核心概念之一。在Java中,线程在其生命周期中会经历多种状态,这些状态反映了线程在不同时间点的行为特征。本教程将详细介绍Java线程的所有状态、状态转换条件以及实际应用示例。
线程状态概述[编辑 | 编辑源代码]
在Java中,线程的状态由
java.lang.Thread.State
枚举定义,包含以下6种状态:
- (新建)
NEW
- (可运行)
RUNNABLE
- (阻塞)
BLOCKED
- (等待)
WAITING
- (计时等待)
TIMED_WAITING
- (终止)
TERMINATED
通过
Thread.getState()
方法可以获取当前线程的状态。
状态转换图[编辑 | 编辑源代码]
以下Mermaid图展示了线程状态的完整转换流程:
详细状态说明[编辑 | 编辑源代码]
1. NEW(新建)[编辑 | 编辑源代码]
线程被创建但尚未启动时的状态。
Thread thread = new Thread(() -> System.out.println("Running"));
System.out.println(thread.getState()); // 输出: NEW
2. RUNNABLE(可运行)[编辑 | 编辑源代码]
线程调用
start()
后进入此状态,包括:
- 正在CPU上执行
- 就绪状态(等待CPU调度)
thread.start();
System.out.println(thread.getState()); // 可能输出: RUNNABLE
3. BLOCKED(阻塞)[编辑 | 编辑源代码]
线程因等待获取同步锁而阻塞。例如:
public class BlockedExample {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread t1 = new Thread(() -> {
synchronized (lock) {
while (true); // 无限持有锁
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) {
System.out.println("Lock acquired");
}
});
t1.start();
Thread.sleep(100); // 确保t1先获取锁
t2.start();
Thread.sleep(100);
System.out.println(t2.getState()); // 输出: BLOCKED
}
}
4. WAITING(无限等待)[编辑 | 编辑源代码]
通过以下方法进入此状态:
- (未指定超时)
Object.wait()
- (未指定超时)
Thread.join()
public class WaitingExample {
public static void main(String[] args) throws InterruptedException {
Thread mainThread = Thread.currentThread();
Thread t = new Thread(() -> {
try {
Thread.sleep(2000);
System.out.println(mainThread.getState()); // 输出: WAITING
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t.start();
t.join(); // 主线程等待t结束
}
}
5. TIMED_WAITING(计时等待)[编辑 | 编辑源代码]
与
WAITING
类似,但带有超时参数:
Thread.sleep(long)
Object.wait(long)
Thread.join(long)
Thread.sleep(1000);
System.out.println(Thread.currentThread().getState());
// 在sleep期间输出: TIMED_WAITING
6. TERMINATED(终止)[编辑 | 编辑源代码]
线程执行完
run()
方法或抛出未捕获异常后的状态。
Thread t = new Thread(() -> System.out.println("Done"));
t.start();
Thread.sleep(100);
System.out.println(t.getState()); // 输出: TERMINATED
实际应用案例[编辑 | 编辑源代码]
线程池监控[编辑 | 编辑源代码]
通过检查线程状态实现线程池健康监测:
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// 监控线程状态
new Thread(() -> {
while (true) {
executor.execute(() -> {
System.out.println("Current state: " +
Thread.currentThread().getState());
});
try { Thread.sleep(1000); } catch (InterruptedException e) {}
}
}).start();
常见问题[编辑 | 编辑源代码]
- Q: WAITING和BLOCKED的区别?
A:
BLOCKED
是等待获取锁,
WAITING
是主动放弃锁并等待唤醒。
- Q: 如何避免线程永久阻塞?
A: 使用
wait(long)
替代无参
wait()
,或设计超时机制。
总结[编辑 | 编辑源代码]
理解线程状态对于调试多线程程序至关重要。关键要点:
- 状态转换由JVM内部机制和显式API调用控制
- 实际包含操作系统层面的"运行"和"就绪"两种子状态
RUNNABLE
- 合理使用可提高系统健壮性
TIMED_WAITING
通过
jstack
工具或Java Mission Control可以实时观察线程状态,这是分析死锁或性能问题的标准方法。