Java 线程生命周期详解
Java线程生命周期包含6种状态:NEW(新建)、RUNNABLE(可运行)、BLOCKED(阻塞)、WAITING(等待)、TIMED_WAITING(计时等待)和TERMINATED(终止)。NEW状态通过start()进入RUNNABLE;RUNNABLE可能因锁竞争转为BLOCKED,或因wait()/sleep()转为WAITING/TIMED_WAITING;最终线程执行完毕进入TER
1. 线程状态概述
Java 线程在其生命周期中有 6 种状态,定义在 java.lang.Thread.State 枚举中:
public enum State {
NEW, // 新建
RUNNABLE, // 可运行
BLOCKED, // 阻塞
WAITING, // 等待
TIMED_WAITING, // 计时等待
TERMINATED // 终止
}
2. 详细状态解析
2.1 NEW(新建状态)
线程对象被创建但尚未启动。
public class ThreadNewState {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("线程执行");
});
System.out.println("线程状态: " + thread.getState()); // NEW
// 线程在start()之前的状态始终是NEW
System.out.println("线程是否存活: " + thread.isAlive()); // false
System.out.println("线程ID: " + thread.getId()); // 有ID但未启动
}
}
特征:
-
已创建Thread对象
-
尚未调用start()方法
-
不消耗系统资源(仅Java对象)
2.2 RUNNABLE(可运行状态)
调用start()方法后,线程处于可运行状态。
public class ThreadRunnableState {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
// 模拟CPU密集型任务
long sum = 0;
for (int i = 0; i < 1000000; i++) {
sum += i;
}
System.out.println("计算完成: " + sum);
});
thread.start();
System.out.println("线程状态: " + thread.getState()); // RUNNABLE
// RUNNABLE包含两种子状态:
// 1. READY: 就绪,等待CPU分配时间片
// 2. RUNNING: 正在CPU上执行
// 获取线程信息
System.out.println("线程名称: " + thread.getName());
System.out.println("线程优先级: " + thread.getPriority());
System.out.println("是否守护线程: " + thread.isDaemon());
}
}
重要说明:
-
RUNNABLE 状态包含操作系统层面的就绪和运行两种状态
-
JVM 不区分这两种状态,都视为 RUNNABLE
-
线程可能正在执行,也可能在等待CPU时间片
2.3 BLOCKED(阻塞状态)
线程等待获取监视器锁(synchronized)时进入阻塞状态。
public class ThreadBlockedState {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("线程1获取锁,持有5秒");
Thread.sleep(5000); // 持有锁5秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(() -> {
System.out.println("线程2尝试获取锁...");
synchronized (lock) {
System.out.println("线程2获取到锁");
}
});
thread1.start();
Thread.sleep(100); // 确保thread1先获取锁
thread2.start();
Thread.sleep(100); // 确保thread2开始执行
// thread2会阻塞,因为lock被thread1持有
System.out.println("线程2状态: " + thread2.getState()); // BLOCKED
thread1.join();
thread2.join();
}
}
触发条件:
-
等待进入 synchronized 方法/代码块
-
调用 wait() 后重新进入同步块(需重新竞争锁)
-
等待 ReentrantLock(不同于 synchronized)
重要区别:
public class BlockedVsSynchronized {
// synchronized方式 - 会进入BLOCKED状态
public synchronized void syncMethod() {
// 方法体
}
// Lock接口方式 - 不会进入BLOCKED状态(而是WAITING/TIMED_WAITING)
private final Lock lock = new ReentrantLock();
public void lockMethod() {
lock.lock(); // 如果锁被占用,线程进入WAITING状态(AQS队列)
try {
// 方法体
} finally {
lock.unlock();
}
}
}
2.4 WAITING(无限期等待)
线程等待其他线程的特定操作(通知或中断)。
public class ThreadWaitingState {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread waitingThread = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("线程即将进入WAITING状态");
lock.wait(); // 释放锁并等待
System.out.println("线程被唤醒");
} catch (InterruptedException e) {
System.out.println("线程被中断");
}
}
});
waitingThread.start();
Thread.sleep(100); // 确保线程启动并进入wait()
System.out.println("线程状态: " + waitingThread.getState()); // WAITING
// 3秒后唤醒线程
Thread.sleep(3000);
synchronized (lock) {
lock.notify(); // 唤醒一个等待线程
// lock.notifyAll(); // 唤醒所有等待线程
}
waitingThread.join();
}
}
进入WAITING的方法:
-
Object.wait()- 不设置超时 -
Thread.join()- 不设置超时 -
LockSupport.park()- LockSupport类
唤醒方式:
-
Object.notify()/notifyAll() -
LockSupport.unpark(thread) -
线程被中断(
thread.interrupt())
2.5 TIMED_WAITING(计时等待)
线程等待指定的时间。
public class ThreadTimedWaitingState {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
try {
System.out.println("线程开始休眠3秒");
Thread.sleep(3000); // 进入TIMED_WAITING
// 或者使用带超时的wait
// Object lock = new Object();
// synchronized (lock) {
// lock.wait(3000);
// }
} catch (InterruptedException e) {
System.out.println("休眠被中断");
}
});
thread.start();
Thread.sleep(100); // 确保线程启动
System.out.println("线程状态: " + thread.getState()); // TIMED_WAITING
// 监控状态变化
for (int i = 0; i < 4; i++) {
System.out.println("第" + i + "秒,线程状态: " + thread.getState());
Thread.sleep(1000);
}
thread.join();
}
}
进入TIMED_WAITING的方法:
-
Thread.sleep(millis) -
Object.wait(timeout) -
Thread.join(timeout) -
LockSupport.parkNanos(nanos) -
LockSupport.parkUntil(deadline)
与WAITING的区别:
-
TIMED_WAITING:超时自动唤醒
-
WAITING:需要其他线程显式唤醒
2.6 TERMINATED(终止状态)
线程执行完毕。
public class ThreadTerminatedState {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
System.out.println("线程开始执行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程执行结束");
});
System.out.println("启动前状态: " + thread.getState()); // NEW
System.out.println("是否存活: " + thread.isAlive()); // false
thread.start();
Thread.sleep(500);
System.out.println("执行中状态: " + thread.getState()); // TIMED_WAITING
System.out.println("是否存活: " + thread.isAlive()); // true
thread.join(); // 等待线程结束
System.out.println("结束后状态: " + thread.getState()); // TERMINATED
System.out.println("是否存活: " + thread.isAlive()); // false
}
}
线程终止的三种方式:
-
正常结束:run()方法执行完毕
-
异常终止:run()方法抛出未捕获异常
-
强制终止:调用stop()方法(已废弃,不安全)
3. 完整状态转换图
NEW
↓ (start())
RUNNABLE ←─────────────────────────────────────────────┐
↓ (等待锁) │
BLOCKED ←───┐ │
↓ (获取锁) │
RUNNABLE │ │
↓ (wait()/join()/park()) │
WAITING ────┼───→ RUNNABLE (notify()/notifyAll()/unpark())│
↓ (带超时的方法) │
TIMED_WAITING ──┼───→ RUNNABLE (超时/通知/中断) │
↓ (run()结束) │
TERMINATED │ │
└───────────────────────────────────────────┘
(中断:interrupt())
4. 状态转换详解
4.1 状态转换表
| 当前状态 | 转换条件 | 目标状态 |
|---|---|---|
| NEW | 调用 start() | RUNNABLE |
| RUNNABLE | 等待 synchronized 锁 | BLOCKED |
| RUNNABLE | 调用 wait() / join() / LockSupport.park() | WAITING |
| RUNNABLE | 调用 sleep() / wait(timeout) / join(timeout) | TIMED_WAITING |
| RUNNABLE | run() 执行完成 | TERMINATED |
| BLOCKED | 获取到锁 | RUNNABLE |
| WAITING | 被 notify() / notifyAll() / unpark() / interrupt() | RUNNABLE |
| TIMED_WAITING | 超时 / 被唤醒 / 中断 | RUNNABLE |
| WAITING/TIMED_WAITING | 等待过程中被中断 | RUNNABLE(抛出InterruptedException) |
4.2 完整状态转换示例
public class ThreadFullLifecycle {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
System.out.println("=== 线程完整生命周期演示 ===");
Thread thread = new Thread(() -> {
System.out.println("1. 线程启动,进入RUNNABLE状态");
synchronized (lock) {
System.out.println("2. 获取锁,执行同步代码块");
try {
System.out.println("3. 调用wait(2000),进入TIMED_WAITING");
lock.wait(2000); // 释放锁,等待2秒
System.out.println("5. 被唤醒,重新获取锁,继续执行");
System.out.println("6. 调用wait(),进入WAITING状态");
lock.wait(); // 无限期等待
System.out.println("8. 再次被唤醒");
} catch (InterruptedException e) {
System.out.println("线程被中断");
}
}
System.out.println("9. 线程执行完毕");
});
// 初始状态:NEW
System.out.println("初始状态: " + thread.getState());
// 启动线程
thread.start();
Thread.sleep(100);
System.out.println("启动后状态: " + thread.getState());
// 等待线程进入wait(2000)
Thread.sleep(100);
System.out.println("调用wait(2000)后状态: " + thread.getState());
// 等待2.1秒(超过wait超时时间)
Thread.sleep(2100);
System.out.println("wait(2000)超时后状态: " + thread.getState());
// 唤醒无限期wait
Thread.sleep(100);
synchronized (lock) {
lock.notify(); // 唤醒线程
}
// 等待线程结束
Thread.sleep(100);
System.out.println("notify后状态: " + thread.getState());
// 再次唤醒(如果还在wait)
Thread.sleep(100);
synchronized (lock) {
lock.notify();
}
thread.join();
System.out.println("最终状态: " + thread.getState());
}
}
5. 特殊状态转换场景
5.1 线程中断(Interrupt)
public class ThreadInterruptExample {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
try {
System.out.println("线程开始休眠10秒");
Thread.sleep(10000);
System.out.println("休眠正常结束");
} catch (InterruptedException e) {
System.out.println("线程被中断!");
System.out.println("中断后状态: " + Thread.currentThread().getState());
System.out.println("中断标志: " + Thread.currentThread().isInterrupted());
// 恢复中断状态(最佳实践)
Thread.currentThread().interrupt();
}
});
thread.start();
Thread.sleep(2000); // 等待2秒
System.out.println("中断前状态: " + thread.getState()); // TIMED_WAITING
System.out.println("中断标志: " + thread.isInterrupted()); // false
thread.interrupt(); // 中断线程
Thread.sleep(100);
System.out.println("中断后状态: " + thread.getState()); // RUNNABLE
System.out.println("中断标志: " + thread.isInterrupted()); // false(异常清除了标志)
thread.join();
}
}
5.2 join() 方法状态转换
public class ThreadJoinExample {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
try {
System.out.println("Thread1 开始执行");
Thread.sleep(2000);
System.out.println("Thread1 执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread thread2 = new Thread(() -> {
System.out.println("Thread2 等待 Thread1");
try {
thread1.join(); // Thread2进入WAITING状态,等待Thread1结束
System.out.println("Thread1 已结束,Thread2 继续执行");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread1.start();
thread2.start();
// 监控状态
try {
Thread.sleep(500);
System.out.println("Thread2状态 (等待join): " + thread2.getState()); // WAITING
Thread.sleep(2000);
System.out.println("Thread2状态 (join完成): " + thread2.getState()); // TERMINATED
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5.3 yield() 方法 - 不会改变状态
public class ThreadYieldExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("执行第 " + i + " 次");
Thread.yield(); // 让出CPU,但状态保持RUNNABLE
}
});
thread.start();
// yield()不会改变线程状态,始终是RUNNABLE
// 只是给调度器一个提示,可以切换到其他线程
}
}
6. 实际应用中的状态监控
6.1 线程状态监控工具
public class ThreadMonitor {
public static void monitorThread(Thread thread, String threadName) {
new Thread(() -> {
while (thread.isAlive()) {
System.out.println(threadName + " 状态: " + thread.getState());
try {
Thread.sleep(500); // 每500ms监控一次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(threadName + " 已终止,最终状态: " + thread.getState());
}).start();
}
public static void main(String[] args) throws InterruptedException {
Thread worker = new Thread(() -> {
System.out.println("工作线程开始");
try {
Thread.sleep(1000); // TIMED_WAITING
synchronized (ThreadMonitor.class) {
ThreadMonitor.class.wait(); // WAITING
}
Thread.sleep(500); // TIMED_WAITING
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("工作线程结束");
});
// 启动监控
monitorThread(worker, "Worker线程");
// 启动工作线程
worker.start();
// 等待然后唤醒
Thread.sleep(2000);
synchronized (ThreadMonitor.class) {
ThreadMonitor.class.notify();
}
worker.join();
}
}
6.2 线程池中的线程状态
public class ThreadPoolStateExample {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
// 提交任务
Future<?> future1 = executor.submit(() -> {
System.out.println("任务1开始");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务1结束");
});
Future<?> future2 = executor.submit(() -> {
System.out.println("任务2开始");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务2结束");
});
// 线程池中的线程状态
Thread.sleep(1000);
// 查看任务状态
System.out.println("任务1是否完成: " + future1.isDone());
System.out.println("任务2是否完成: " + future2.isDone());
// 获取线程池中的工作线程(需要扩展ThreadPoolExecutor)
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
}
}
7. 状态相关API总结
7.1 Thread类相关方法
| 方法 | 说明 | 影响状态 |
|---|---|---|
start() |
启动线程 | NEW → RUNNABLE |
run() |
线程执行体 | 无状态变化 |
sleep(long) |
睡眠指定时间 | RUNNABLE → TIMED_WAITING |
yield() |
让出CPU时间片 | 保持RUNNABLE |
join() |
等待线程结束 | RUNNABLE → WAITING |
join(long) |
限时等待线程结束 | RUNNABLE → TIMED_WAITING |
interrupt() |
中断线程 | 可能从WAITING/TIMED_WAITING → RUNNABLE |
isInterrupted() |
检查中断标志 | 无状态变化 |
isAlive() |
线程是否存活 | NEW/TERMINATED返回false |
getState() |
获取线程状态 | 无状态变化 |
7.2 Object类相关方法
| 方法 | 说明 | 影响状态 |
|---|---|---|
wait() |
无限期等待 | RUNNABLE → WAITING |
wait(long) |
限时等待 | RUNNABLE → TIMED_WAITING |
notify() |
唤醒一个等待线程 | WAITING/TIMED_WAITING → RUNNABLE |
notifyAll() |
唤醒所有等待线程 | WAITING/TIMED_WAITING → RUNNABLE |
8. 常见问题与最佳实践
8.1 避免线程泄漏
public class ThreadLeakPrevention {
public static void main(String[] args) {
// 错误示例:线程永远WAITING,无法终止
Thread leakThread = new Thread(() -> {
synchronized (ThreadLeakPrevention.class) {
try {
ThreadLeakPrevention.class.wait(); // 永远等待
} catch (InterruptedException e) {
// 没有正确处理中断
}
}
});
leakThread.start();
// 正确示例:使用超时或可中断的等待
Thread safeThread = new Thread(() -> {
synchronized (ThreadLeakPrevention.class) {
try {
ThreadLeakPrevention.class.wait(30000); // 30秒超时
} catch (InterruptedException e) {
System.out.println("线程被中断,正常退出");
Thread.currentThread().interrupt(); // 恢复中断状态
return; // 退出线程
}
}
});
safeThread.start();
}
}
8.2 正确处理线程中断
public class ProperInterruptHandling {
public static void main(String[] args) throws InterruptedException {
Thread worker = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("工作中...");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("接收到中断信号");
// 两种选择:
// 1. 退出线程
Thread.currentThread().interrupt(); // 重新设置中断标志
break;
// 2. 继续执行(如果允许)
}
}
System.out.println("线程结束");
});
worker.start();
Thread.sleep(3500);
worker.interrupt(); // 发送中断信号
worker.join();
}
}
8.3 状态诊断工具
public class ThreadDiagnosis {
// 诊断线程死锁
public static void diagnoseDeadlock() {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadMXBean.findDeadlockedThreads();
if (threadIds != null) {
ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadIds);
System.out.println("发现死锁线程:");
for (ThreadInfo info : threadInfos) {
System.out.println("线程: " + info.getThreadName());
System.out.println("状态: " + info.getThreadState());
LockInfo[] lockedSyncs = info.getLockedSynchronizers();
for (LockInfo lock : lockedSyncs) {
System.out.println("持有锁: " + lock);
}
}
}
}
// 监控所有线程状态
public static void monitorAllThreads() {
Map<Thread.State, Integer> stateCount = new HashMap<>();
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread thread : threadSet) {
Thread.State state = thread.getState();
stateCount.put(state, stateCount.getOrDefault(state, 0) + 1);
}
System.out.println("=== 线程状态统计 ===");
stateCount.forEach((state, count) -> {
System.out.println(state + ": " + count + "个线程");
});
}
}
9. 总结
9.1 状态转换要点
-
NEW → RUNNABLE: 只能通过
start()转换 -
RUNNABLE → BLOCKED: 只在 synchronized 锁竞争时发生
-
RUNNABLE → WAITING/TIMED_WAITING: 调用特定方法
-
WAITING/TIMED_WAITING → RUNNABLE: 被唤醒、超时或中断
-
RUNNABLE → TERMINATED: 线程执行完毕
9.2 最佳实践
-
避免使用已废弃的方法:如
stop(),suspend(),resume() -
合理使用中断机制:作为线程退出的优雅方式
-
注意锁的粒度:减少线程在BLOCKED状态的时间
-
使用超时机制:避免线程永远WAITING
-
监控线程状态:及时发现死锁、线程泄漏等问题
9.3 性能影响
-
RUNNABLE: CPU资源竞争
-
BLOCKED: 锁竞争,可能成为瓶颈
-
WAITING/TIMED_WAITING: 资源等待,可能影响响应时间
-
上下文切换: 状态切换会消耗CPU资源
理解线程生命周期对于编写高性能、稳定的多线程应用至关重要。合理管理线程状态可以避免死锁、提高资源利用率,并确保应用的正确性。
更多推荐


所有评论(0)