一文搞懂线程的生命周期以及状态

一. Java 线程生命周期概述

Java 中的线程生命周期主要分为以下五个状态:

  • 新建状态(NEW):线程被创建但尚未启动。
  • 可运行状态(RUNNABLE):线程可以被操作系统调度执行。
  • 阻塞状态(BLOCKED):线程正在等待获取锁,无法继续执行。
  • 等待状态(WAITING):线程等待另一个线程显式地唤醒它。
  • 超时状态(TIMED_WAITING):线程在等待指定时间后可以继续执行。
  • 终止状态(TERMINATED):线程已经执行完毕或因异常终止。
二. 线程生命周期图示

这里借用一下二哥的图片

在上图中,我们可以清晰地看到 Java 线程生命周期中各个状态及它们之间的转换关系。

三. 各个状态的详细解释
1. 新建状态(NEW)

当线程对象被创建时,线程处于新建状态。这时,线程尚未开始执行。可以通过调用 new Thread()new Thread(Runnable target) 来创建新线程。此时,线程还没有开始运行,需要调用 start() 方法才能进入下一阶段。

2. 可运行状态(RUNNABLE)

线程调用了 start() 方法后,进入可运行状态。在该状态下,线程可能正在运行,也可能在等待操作系统的调度。Java 中的 RUNNABLE 包括了操作系统中的就绪(Ready)和运行(Running)状态。线程在这个状态下能够获得 CPU 时间片并执行任务。

3. 阻塞状态(BLOCKED)

当一个线程试图获取一个已经被其他线程占用的锁时,它会进入阻塞状态。在这种情况下,线程无法继续执行,直到锁被释放。

阻塞状态会严重影响多线程程序的性能,因此合理的锁管理对于并发编程至关重要。

4. 等待状态(WAITING)

线程调用 Object.wait()Thread.join() 方法时,进入等待状态。此时,线程等待其他线程通过 notify()notifyAll() 方法显式唤醒它。

WAITING 状态下,线程不消耗 CPU 时间片,但仍然被认为是活动线程。

5. 超时等待状态(TIMED_WAITING)

线程可以在调用带有超时参数的方法时进入超时等待状态,比如 Thread.sleep()Object.wait(long timeout)。在这种状态下,线程会等待指定时间,然后自动唤醒。

线程在超时等待状态结束后,会重新进入可运行状态。

6. 终止状态(TERMINATED)

当线程的 run() 方法执行完成或遇到异常而退出时,线程进入终止状态。此时,线程生命周期结束,无法再次启动。

在终止状态下,线程的所有资源都会被回收,无法再次进入其他状态。

四. 状态转换的关键方法

Java 中,线程状态的转换由一系列方法控制。以下是一些常用方法及其对应的状态转换:

  • start():从 新建状态 进入 可运行状态
  • wait():从 可运行状态 进入 等待状态
  • sleep():从 可运行状态 进入 超时等待状态
  • join():从 可运行状态 进入 等待状态,直到指定线程执行完成。
  • notify() / notifyAll():从 等待状态 返回 可运行状态
  • 线程执行完毕异常退出:从 可运行状态 进入 终止状态
五. 线程生命周期中的常见问题
  • 线程阻塞问题:在阻塞状态下,线程长时间无法获得锁,会导致性能下降,甚至死锁。使用 ReentrantLock 等更灵活的锁机制可以避免这种问题。

  • 线程资源消耗:线程在超时等待或等待状态下虽然不占用 CPU,但仍然消耗系统资源,频繁创建和销毁线程会增加系统开销。可以通过线程池(如 ExecutorService)来管理线程的创建和回收。

  • 线程同步问题:线程之间共享数据时需要同步操作,以避免竞争条件。可以使用 synchronized 关键字、Lock 接口或其他同步机制。

六. 总结

Java 线程的生命周期由多个状态组成,线程可以在这些状态之间进行转换。理解线程的生命周期不仅有助于编写高效的并发程序,还能有效防止死锁、线程阻塞等常见问题。另外java的线程状态和操作系统的线程状态有些许不同,大家可以结合记忆防止混淆。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值