在Java中,线程的生命周期由六种主要状态构成,每种状态都有其特定的转换条件。以下是Java线程的生命周期状态及其转换条件:
线程状态
-
新建(NEW):
- 线程对象已经创建,但尚未调用
start()
方法。
Thread thread = new Thread();
- 线程对象已经创建,但尚未调用
-
就绪(RUNNABLE):
- 线程已调用
start()
方法,等待被线程调度器选中以便运行。需要注意的是,在某些文档中,这个状态也被称为“可运行(RUNNABLE)”,包括实际运行状态。
thread.start();
- 线程已调用
-
运行(RUNNING):
- 线程调度器从就绪线程池中选中该线程,并开始执行
run()
方法中的代码。
- 线程调度器从就绪线程池中选中该线程,并开始执行
-
阻塞(BLOCKED):
- 线程在等待获取一个监视器锁,以便进入同步块/方法。如果线程在同步代码块/方法中等待锁,它就是阻塞状态。
synchronized (lock) {// 线程进入同步块 }
-
等待(WAITING):
- 线程等待另一线程显式地唤醒。进入这种状态有几种方法:调用
Object.wait()
、Thread.join()
、或LockSupport.park()
,并且没有设置超时时间。
synchronized (lock) {lock.wait(); // 必须在 synchronized 块内调用 }
- 线程等待另一线程显式地唤醒。进入这种状态有几种方法:调用
-
超时等待(TIMED_WAITING):
- 线程等待一定时间之后会自动唤醒。进入这种状态的几种方法包括:
Thread.sleep(long millis)
、Object.wait(long timeout)
、Thread.join(long millis)
、LockSupport.parkNanos()
、和LockSupport.parkUntil()
。
Thread.sleep(1000); // 休眠 1 秒
- 线程等待一定时间之后会自动唤醒。进入这种状态的几种方法包括:
-
终止(TERMINATED):
- 线程已执行完毕或由于异常退出,线程结束生命周期。
状态转换
线程在其生命周期中会在不同状态之间进行转换,主要的转换条件如下:
-
新建 -> 就绪:
- 调用
start()
方法。
Thread thread = new Thread(); thread.start();
- 调用
-
就绪 -> 运行:
- 线程调度器选择该线程进行执行。
-
运行 -> 阻塞:
- 线程尝试获取同步锁,但锁被其他线程持有。
synchronized (lock) {// 线程进入阻塞状态等待锁 }
-
运行 -> 等待:
- 线程调用
Object.wait()
方法或Thread.join()
方法,没有设置超时。
synchronized (lock) {lock.wait(); }
- 线程调用
-
运行 -> 超时等待:
- 线程调用
Thread.sleep(long millis)
方法、Object.wait(long timeout)
方法、或Thread.join(long millis)
方法,并设置了超时。
Thread.sleep(1000);
- 线程调用
-
等待 -> 就绪:
- 其他线程调用
Object.notify()
或Object.notifyAll()
方法。
synchronized (lock) {lock.notify(); }
- 其他线程调用
-
超时等待 -> 就绪:
- 超时时间到。
// 等待时间到后自动进入就绪状态
-
阻塞 -> 就绪:
- 线程获得锁。
synchronized (lock) {// 获得锁,进入就绪状态 }
-
运行 -> 终止:
- 线程执行完成或抛出未捕获的异常。
public void run() {// 执行完毕或抛出异常,线程终止 }
示例代码
以下是一个简单的示例代码,演示了线程在不同状态之间的转换:
public class ThreadLifecycleDemo {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {try {System.out.println("Thread State: " + Thread.currentThread().getState()); // RUNNABLEThread.sleep(1000);synchronized (ThreadLifecycleDemo.class) {ThreadLifecycleDemo.class.wait();}} catch (InterruptedException e) {e.printStackTrace();}});System.out.println("Thread State after creation: " + thread.getState()); // NEWthread.start();System.out.println("Thread State after start: " + thread.getState()); // RUNNABLEThread.sleep(500);System.out.println("Thread State while sleeping: " + thread.getState()); // TIMED_WAITINGsynchronized (ThreadLifecycleDemo.class) {ThreadLifecycleDemo.class.notify();}Thread.sleep(500);System.out.println("Thread State after notify: " + thread.getState()); // TERMINATED}
}
在上述示例中,通过打印线程的状态,可以观察到线程在其生命周期中的状态变化。了解这些状态和转换条件对于编写并发程序和调试多线程问题非常重要。