Java线程是怎么实现run方法的执行的呢?

Java中的线程由java.lang.Thread类表示。当我们创建一个线程并调用其start()方法时,Java虚拟机(JVM)会为该线程分配执行资源并开始执行该线程的run()方法。

以下是Java线程启动和执行run()方法的基本流程:

  1. 创建一个Thread对象或其子类的对象。这通常涉及到定义一个run()方法。
  2. 调用该对象的start()方法。
  3. start()方法通知JVM创建一个新的线程并开始执行。
  4. JVM调用run()方法。

使用流程图表示如下:

sql 复制代码
     +-------------------+
     | Create Thread obj |
     +-------------------+
              |
              v
     +-------------------+
     | Call start()      |
     +-------------------+
              |
              v
     +-------------------+
     | JVM allocates     |
     | execution resources|
     +-------------------+
              |
              v
     +-------------------+
     | JVM calls run()   |
     +-------------------+

重要点:

  • 只有通过调用start()方法,JVM才会为线程分配必要的资源并执行run()方法。直接调用run()方法不会启动新的线程,而只是在当前线程中执行run()方法。
  • 每个Thread对象只能被start()一次。多次调用会抛出IllegalThreadStateException

最佳实践是,不要直接继承Thread类来创建线程,而是实现Runnable接口,并将其传递给Thread的构造函数。这种方法更加灵活,允许你更容易地重用代码和合并资源。


在Java中,主要有两种方法创建多线程:

  1. 继承 Thread:

    • 步骤:

      1. 定义一个类继承Thread类。
      2. 重写run()方法。
      3. 创建该类的实例。
      4. 调用该实例的start()方法。
    • 示例:

      typescript 复制代码
       class MyThread extends Thread {
           public void run() {
               System.out.println("Thread is running");
           }
       }
       ​
       public class Test {
           public static void main(String[] args) {
               MyThread t = new MyThread();
               t.start();
           }
       }
    • 优点:

      • 简单,对于小项目或快速原型设计来说容易实现。
    • 缺点:

      • Java不支持多重继承。如果一个类已经继承了其他类,那么它不能再继承Thread类。
      • 不利于代码复用。继承了Thread类的类只能当作线程使用,而不能当作普通的类使用。
  2. 实现 Runnable 接口:

    • 步骤:

      1. 定义一个类实现Runnable接口。
      2. 重写run()方法。
      3. 创建Thread类的实例,并传入Runnable对象。
      4. 调用Thread实例的start()方法。
    • 示例:

      typescript 复制代码
       class MyRunnable implements Runnable {
           public void run() {
               System.out.println("Thread is running");
           }
       }
       ​
       public class Test {
           public static void main(String[] args) {
               MyRunnable r = new MyRunnable();
               Thread t = new Thread(r);
               t.start();
           }
       }
    • 优点:

      • 更加灵活。由于Java支持多接口继承,所以一个类可以实现多个接口,包括Runnable
      • 更易于代码复用。可以独立于线程机制,作为一个普通的类被复用。
      • 与线程的行为解耦。线程的行为(如优先级、守护状态等)由Thread类控制,任务的行为由Runnable对象控制。
    • 缺点:

      • 需要额外创建Thread对象,这在某些情况下可能会增加轻微的复杂性。

总结:

尽管可以通过继承Thread类来创建线程,但大多数情况下,实现Runnable接口是更好的选择,因为它提供了更大的灵活性和更好的代码复用性。另外,Java提供的Executor框架也推荐使用Runnable或其更灵活的版本,Callable,来定义并行任务。

相关推荐
程序员爱钓鱼8 分钟前
Go语言实战案例 — 项目实战篇:简易博客系统(支持评论)
前端·后端·go
追逐时光者7 小时前
精选 4 款基于 .NET 开源、功能强大的 Windows 系统优化工具
后端·.net
TF男孩7 小时前
ARQ:一款低成本的消息队列,实现每秒万级吞吐
后端·python·消息队列
AAA修煤气灶刘哥8 小时前
别让Redis「歪脖子」!一次搞定数据倾斜与请求倾斜的捉妖记
redis·分布式·后端
AAA修煤气灶刘哥8 小时前
后端人速藏!数据库PD建模避坑指南
数据库·后端·mysql
你的人类朋友9 小时前
什么是API签名?
前端·后端·安全
昵称为空C11 小时前
SpringBoot3 http接口调用新方式RestClient + @HttpExchange像使用Feign一样调用
spring boot·后端
架构师沉默11 小时前
设计多租户 SaaS 系统,如何做到数据隔离 & 资源配额?
java·后端·架构
RoyLin12 小时前
TypeScript设计模式:适配器模式
前端·后端·node.js
该用户已不存在12 小时前
Mojo vs Python vs Rust: 2025年搞AI,该学哪个?
后端·python·rust