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,来定义并行任务。

相关推荐
绝无仅有6 分钟前
使用 Docker 安装 Elastic Stack 并重置本地密码
后端·面试·github
老A技术联盟19 分钟前
聊一聊消息中间件的后起之秀-pulsar及其实践
后端
隐-梵28 分钟前
Android studio前沿开发--利用socket服务器连接AI实现前后端交互(全站首发思路)
android·服务器·人工智能·后端·websocket·android studio·交互
uhakadotcom31 分钟前
Langflow:零基础快速上手AI流程可视化开发工具详解与实战案例
后端·面试·github
bobz96531 分钟前
strongswan ipsec 端口使用
后端
陈哥聊测试34 分钟前
这款自研底层框架,你说不定已经用上了
前端·后端·开源
一只叫煤球的猫1 小时前
分布式-跨服务事务一致性的常见解决方案
java·分布式·后端
扣丁梦想家1 小时前
Spring Boot 实现 Excel 导出功能(支持前端下载 + 文件流)
spring boot·后端·excel
调试人生的显微镜1 小时前
flutter ios 自定义ios插件
后端
仰望星空的打工人1 小时前
windows11家庭版安装docker
后端