锡林郭勒盟网站建设_网站建设公司_Linux_seo优化
2025/12/31 21:38:04 网站建设 项目流程

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(); } }

触发条件

  1. 等待进入 synchronized 方法/代码块

  2. 调用 wait() 后重新进入同步块(需重新竞争锁)

  3. 等待 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的方法

  1. Object.wait()- 不设置超时

  2. Thread.join()- 不设置超时

  3. 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的方法

  1. Thread.sleep(millis)

  2. Object.wait(timeout)

  3. Thread.join(timeout)

  4. LockSupport.parkNanos(nanos)

  5. 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 } }

线程终止的三种方式

  1. 正常结束:run()方法执行完毕

  2. 异常终止:run()方法抛出未捕获异常

  3. 强制终止:调用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
RUNNABLErun() 执行完成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 状态转换要点

  1. NEW → RUNNABLE: 只能通过start()转换

  2. RUNNABLE → BLOCKED: 只在 synchronized 锁竞争时发生

  3. RUNNABLE → WAITING/TIMED_WAITING: 调用特定方法

  4. WAITING/TIMED_WAITING → RUNNABLE: 被唤醒、超时或中断

  5. RUNNABLE → TERMINATED: 线程执行完毕

9.2 最佳实践

  1. 避免使用已废弃的方法:如stop(),suspend(),resume()

  2. 合理使用中断机制:作为线程退出的优雅方式

  3. 注意锁的粒度:减少线程在BLOCKED状态的时间

  4. 使用超时机制:避免线程永远WAITING

  5. 监控线程状态:及时发现死锁、线程泄漏等问题

9.3 性能影响

  • RUNNABLE: CPU资源竞争

  • BLOCKED: 锁竞争,可能成为瓶颈

  • WAITING/TIMED_WAITING: 资源等待,可能影响响应时间

  • 上下文切换: 状态切换会消耗CPU资源

理解线程生命周期对于编写高性能、稳定的多线程应用至关重要。合理管理线程状态可以避免死锁、提高资源利用率,并确保应用的正确性。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询