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

相关推荐
天天摸鱼的java工程师几秒前
面试官灵魂拷问:如何设计一个支持 10 万 QPS 的秒杀系统?
java·后端·面试
山花1 分钟前
什么是“Pythonic”?——写出更优雅的Python代码(下)
后端·python
无名之逆1 分钟前
Junior Year Self-Study Notes My Journey with the Hyperlane Framework
java·开发语言·前端·spring boot·后端·rust·编程
Android洋芋2 分钟前
详解虚拟内存调整:从零到一的开发实战与企业级优化策略
后端
东东瑞4 分钟前
工作使用AI场景
后端·ai编程
坚持学习永不言弃6 分钟前
JAVA中 `void` 和 `Void` 的区别
后端
武子康9 分钟前
Java-43 深入浅出 Nginx - 基本配置方式 nginx.conf Events块 HTTP块 反向代理 负载均衡
java·后端·nginx·http·负载均衡·运维开发
寻月隐君12 分钟前
bacon 点燃 Rust:比 cargo-watch 更爽的开发体验
后端·rust·github
舰长1151 小时前
mq安装新版-3.13.7的安装
开发语言·后端·ruby
风象南1 小时前
Spring Boot Fat Jar 的三种打包方式
java·spring boot·后端