Java线程生命周期详解及多线程实现方式对比

咖啡半糖
咖啡半糖
发布时间:2026-10-14| 6人浏览过
原创

Java多线程开发是高性能应用的核心基础。掌握线程从创建到销毁的完整生命周期,以及正确选择Thread或Runnable的实现方式,能有效避免资源竞争问题并提升代码扩展性。本文将系统梳理线程状态流转逻辑,并通过经典案例对比两种主流实现方案的异同。

Java线程的五种生命周期状态

在Java中,一个完整的线程对象在其执行过程中会经历五种不同的状态。理解这些状态的转换条件是进行并发编程的前提。

1. 新建状态 (New)

当程序使用 new 关键字创建一个线程对象后,该线程即进入新建状态。此时线程尚未启动,例如执行 Thread thread = new Thread(); 时。

2. 就绪状态 (Runnable)

被称为“可执行状态”。当调用线程对象的 start() 方法后,线程进入就绪状态。此时线程已获得除CPU时间片以外的所有必要资源,随时准备被调度执行。需要注意的是,就绪状态并不保证立即执行,而是等待操作系统分配CPU。

3. 运行状态 (Running)

线程获取CPU使用权并开始执行其 run() 方法体中的逻辑。线程只能从就绪状态直接进入运行状态,不能跳跃。

4. 阻塞状态 (Blocked)

线程由于某种原因主动放弃CPU使用权,暂停执行,直到满足特定条件才重新转入就绪状态。常见的阻塞情况包括三种:

  • 等待阻塞:通过调用 wait() 方法,使线程等待某项工作的完成。
  • 同步阻塞:在获取 synchronized 同步锁失败时(锁已被其他线程占用),线程进入此状态。
  • 其他阻塞:调用 sleep()、join() 或发起I/O请求时进入。当 sleep() 超时、join() 等待结束或I/O处理完毕时,线程重新转入就绪状态。

5. 死亡状态 (Dead)

线程执行完 run() 方法或因未捕获异常退出,标志着线程生命周期的终结。

涉及的核心机制:Object、Thread与synchronized

上述状态的变化深度依赖于JDK底层的几个关键概念:

  • Object类:定义了 wait()、notify()、notifyAll() 等用于线程间通信和休眠/唤醒的方法。之所以将这些方法定义在Object而非Thread中,是因为锁是绑定在对象上的,唤醒操作也需针对特定对象进行。
  • Thread类:提供了丰富的线程操作API,如 sleep()(休眠)、interrupt()(中断)、getName()(获取名称)等。
  • synchronized关键字:用于区分同步代码块和同步方法,确保同一时刻只有一个线程能访问被锁定的资源,解决竞态条件问题。

多线程实现的两种主要方式

在Java中实现多线程,最基础的两种方式是继承 Thread 类和实现 Runnable 接口。理解它们的底层关系有助于编写更高质量的代码。

1. Runnable接口实现

Runnable 是一个函数式接口,仅包含一个抽象方法 run()。其源码结构如下:

public interface Runnable {
  public abstract void run();
}

实现步骤:自定义类实现该接口,并重写 run() 方法;然后创建 Thread 实例,将实现了Runnable的对象传入构造函数:new Thread(new MyRunnable())。

2. Thread类继承实现

Thread 本身就是一个类,且在Java源码中已实现了 Runnable 接口:

public class Thread implements Runnable {}

实现步骤:自定义类直接继承 Thread 类,重写 run() 方法,并调用 start() 启动。

Thread与Runnable的深度对比及推荐

虽然两者都能实现多线程,但在实际开发中存在显著差异:

  • 继承限制:Java不支持多重继承。如果采用继承Thread的方式,子类便无法再继承其他父类,限制了类的扩展能力。而实现Runnable接口没有此限制,更符合面向对象的设计原则。
  • 资源共享:这是两者最大的区别。当多个线程需要共享同一份数据(如库存、车票)时,必须基于同一个Runnable对象创建多个Thread实例。若每个线程都继承独立的Thread对象,则各自拥有独立的数据副本,无法实现共享逻辑。
  • 解耦:Runnable将“任务(做什么)”与“执行者(谁来做)”分离,便于代码维护和复用。

结论:除非需要重写Thread类的特定行为,否则强烈建议使用 Runnable 接口来实现多线程。

代码实战:卖票场景示例

为了直观展示两者的差异,我们通过一个简单的“售票员卖票”案例来对比运行结果。

方式一:继承Thread(多资源,不共享)

在此模式下,我们创建了三个不同的 MyThread 对象(t1, t2, t3),每个对象内部都有一份独立的 ticket 变量。

class MyThread extends Thread{
  private int ticket=10; 
  public void run(){
    for(int i=0;i<20;i++){ 
      if(this.ticket>0){
        System.out.println(this.getName()+" 卖票:ticket"+this.ticket--);
      }
    }
  } 
};

public class ThreadTest { 
  public static void main(String[] args) { 
    // 创建3个独立的线程实例
    MyThread t1=new MyThread();
    MyThread t2=new MyThread();
    MyThread t3=new MyThread();
    
    // 分别启动
    t1.start();
    t2.start();
    t3.start();
  } 
}

结果分析:

每个线程实例都会卖出自己的10张票。总票数并非固定的单一池,而是3个线程各卖10张。这证明了各个线程互不干扰,未实现资源共享。

方式二:实现Runnable(单资源,共享)

在此模式下,我们只创建一个 MyThread 实例(mt),然后将它传递给三个不同的 Thread 构造函数。

class MyThread implements Runnable{ 
  private int ticket=10; 
  public void run(){
    for(int i=0;i<20;i++){ 
      if(this.ticket>0){
        System.out.println(Thread.currentThread().getName()+" 卖票:ticket"+this.ticket--);
      }
    }
  } 
}; 

public class RunnableTest { 
  public static void main(String[] args) { 
    // 只有一个Runnable对象实例
    MyThread mt=new MyThread();

    // 3个线程共用这一个任务对象
    Thread t1=new Thread(mt);
    Thread t2=new Thread(mt);
    Thread t3=new Thread(mt);
    
    t1.start();
    t2.start();
    t3.start();
  } 
}

结果分析:

三个线程交替输出,直到票数为0为止。总计只卖出10张票。这说明 t1、t2、t3 操作的是内存中同一份 ticket 变量,成功实现了资源共享。

总结

线程的生命周期管理是并发编程的基础知识。在实际项目中,优先考虑使用 Runnable 接口实现多线程,不仅因为避免了单继承的限制,更因为它天然适合处理需要共享资源的复杂业务场景。以上就是Java线程状态及多线程实现方式的详细内容,更多关于Java并发编程技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。