- 作者:老汪软件技巧
- 发表时间:2024-09-14 11:02
- 浏览量:
在 Java 中,Thread 类定义了 6 种线程状态,这些状态描述了一个线程的生命周期中的不同阶段。理解这些状态对于编写多线程程序、调试和优化性能非常重要。
本文将详细介绍这六种线程状态,并通过示例代码演示每种状态的行为。此外,还将讨论一些常见的线程方法(如 Thread.sleep() 和 Object.wait())是如何影响线程状态的。
1. 线程状态的定义
Thread.State 是 Java 中枚举类型 Thread 的内部类,用于描述线程的六种状态。定义如下:
public enum State {
// 新建状态:线程对象已经创建,但未调用 start() 方法
NEW,
// 运行状态:线程已经调用 start() 方法,正在运行中
RUNNABLE,
// 阻塞状态:线程试图获取锁但失败,正在等待锁释放
BLOCKED,
// 无限期等待:线程等待某个条件的发生,例如调用了 Object.wait() 方法且没有超时设置
WAITING,
// 有限期等待:线程在一定时间内等待条件的发生,例如调用了 Thread.sleep(n) 或 Object.wait(n)
TIMED_WAITING,
// 终止状态:线程执行完 run() 方法或因异常退出,线程结束
TERMINATED;
}
2. 各种状态演示2.1 NEW 状态
当一个线程被创建时,它处于 NEW 状态。此时线程还没有开始执行,调用 start() 方法后会进入 RUNNABLE 状态。
Thread thread = new Thread(() -> {
System.out.println("Thread is running");
});
System.out.println(thread.getState()); // 输出:NEW
2.2 RUNNABLE 状态
当线程调用 start() 方法后,它进入 RUNNABLE 状态。此时,线程正在 Java 虚拟机中运行,等待 CPU 时间片的分配。
Thread thread = new Thread(() -> {
while (true) {
// 模拟线程正在运行
}
});
thread.start();
System.out.println(thread.getState()); // 输出:RUNNABLE
注意:RUNNABLE 并不一定意味着线程正在运行,而是可能正在等待操作系统分配的 CPU 时间。
2.3 BLOCKED 状态
当线程试图获取一个锁时,如果该锁已经被其他线程占用,线程将进入 BLOCKED 状态,等待锁的释放。
class SyncClass {
public synchronized void syncMethod() {
while (true) {
// 模拟线程占用锁
}
}
}
SyncClass syncClass = new SyncClass();
Thread thread1 = new Thread(() -> syncClass.syncMethod());
Thread thread2 = new Thread(() -> syncClass.syncMethod());
thread1.start();
thread2.start();
Thread.sleep(1000); // 让 thread1 获得锁
System.out.println(thread2.getState()); // 输出:BLOCKED
2.4 WAITING 状态
线程在 WAITING 状态下,会一直等待其他线程的通知或者中断。这种状态通常通过调用没有超时的 Object.wait()、Thread.join()、或 LockSupport.park() 等方法来进入。
Object lock = new Object();
Thread thread = new Thread(() -> {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
Thread.sleep(1000); // 等待线程进入 wait 状态
System.out.println(thread.getState()); // 输出:WAITING
2.5 TIMED_WAITING 状态
线程在 TIMED_WAITING 状态下,会在有限的时间内等待其他线程的通知或中断。线程调用 Thread.sleep(n)、Object.wait(n)、或 Thread.join(n) 等带有超时参数的方法时会进入此状态。
2.5.1 Thread.sleep(n)
Thread.sleep(n) 方法将使当前线程休眠 n 毫秒,这期间线程进入 TIMED_WAITING 状态。
Thread thread = new Thread(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
Thread.sleep(1000); // 在 thread 睡眠期间
System.out.println(thread.getState()); // 输出:TIMED_WAITING
2.5.2 Object.wait(n)
类似于 Thread.sleep(),Object.wait(n) 方法也会使线程在等待通知时,进入 TIMED_WAITING 状态,不过这里的 wait() 是与锁相关联的。
Object lock = new Object();
Thread thread = new Thread(() -> {
synchronized (lock) {
try {
lock.wait(2000); // 等待 2 秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
Thread.sleep(1000);
System.out.println(thread.getState()); // 输出:TIMED_WAITING
2.6 TERMINATED 状态
当线程执行完 run() 方法或抛出未捕获的异常时,线程进入 TERMINATED 状态。此时线程生命周期结束,无法再次启动。
示例代码:
Thread thread = new Thread(() -> {
System.out.println("Thread finished");
});
thread.start();
thread.join(); // 等待线程执行完毕
System.out.println(thread.getState()); // 输出:TERMINATED
3. 常见问题解答3.1 Thread.sleep(0) 会做什么?
Thread.sleep(0) 并不会使线程进入 TIMED_WAITING 状态,因为它不会真正休眠。实际上,它只是一个提示给线程调度器,允许其他线程获取 CPU 时间。如果没有其他线程需要执行,该线程可能会继续运行。
3.2 Object.wait(0) 和 Object.wait() 的区别
Object.wait(0) 和 Object.wait() 的效果相同:都使线程进入 WAITING 状态,并等待其他线程调用 notify() 或 notifyAll() 使其苏醒。参数 0 表示无限期等待。
3.3 什么状态会释放cpu资源?3.3.1 WAITING
线程处于 无限期等待 状态时,会释放 CPU 资源。线程调用以下方法进入 WAITING 状态:
此时线程会暂停执行,直到其他线程通过 notify()、notifyAll()、unpark() 或者 join() 目标线程结束来唤醒它。
3.3.2 TIMED_WAITING
线程进入 有超时的等待 状态时,同样会释放 CPU 资源。线程调用以下方法进入 TIMED_WAITING 状态:
线程会等待指定时间,或者被唤醒后继续执行。
3.3.3 BLOCKED
线程进入 阻塞 状态时,会等待同步锁的释放,并释放 CPU 资源。当其他线程释放该锁时,BLOCKED 状态的线程才有机会获取锁并进入 RUNNABLE 状态。
3.3.4 TERMINATED
线程执行完毕或抛出未捕获的异常进入 终止状态 时,它将不再占用 CPU 资源,因为线程生命周期已经结束。
3.4 什么状态会释放Synchronized锁资源?3.4.1 WAITING 和 TIMED_WAITING
当线程调用 Object.wait() 或 Object.wait(n) 进入等待状态时,线程会释放当前持有的同步锁。这是因为 wait() 方法在内部会使线程释放锁,进入等待队列,直到通过 notify() 或 notifyAll() 被唤醒。
3.4.3 TERMINATED
线程执行完毕或抛出未捕获异常进入 TERMINATED 状态时,会自动释放它持有的所有同步锁。
4. 线程状态的转换图
下图展示了 Java 线程的状态流转过程:
5. 总结
Java 中的线程状态为我们提供了分析线程行为的重要工具。在实际编程中,理解每个状态的意义以及如何触发状态变化,可以帮助我们编写更高效、可靠的多线程应用程序。