当前位置: 首页 > news >正文

【面试题】深度解析Java多线程中的 run() 与 start() 有什么区别?

【面试题】深度解析Java多线程中的 run() 与 start() 有什么区别?

大多数人的回答

start()

run()

深入底层源码的解析 run() 与 start() 

为什么我们不能直接调用 run() 方法?

如何证明 start() 会调用 run() 方法?

JVM -> OS执行全流程 !!!

完整流程图 


【面试题】深度解析Java多线程中的 run() 与 start() 有什么区别?

大多数人的回答

下面这个是我2022年6月写的文章,当时刚刚学多线程,所以对这个问题的理解很片面~~~  

下文是现在2022.11.30,我对其新的见解!站在JVM底层源码的角度来解析这个问题!!! 

Java多线程编程(一)——线程的3种实现方法_面向鸿蒙编程的博客-CSDN博客https://blog.csdn.net/weixin_43715214/article/details/122329166

start()

start() 方法是启动线程,并由 JVM 来调用线程的 run() 方法执行,是真正的多线程!

这时此线程是处于就绪状态, 并没有运行。这时无需等待 run 方法体代码执行完毕,可以直接继续执行下面的代码。 

run()

run() 方法里面封装的是需要被线程执行的逻辑代码,如果直接调用run()方法和调用普通方法没有区别(单线程)!

run() 可以重复调用,而 start()只能调用一次


深入底层源码的解析 run() 与 start() 

为什么我们不能直接调用 run() 方法?

如果直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。

调用 start 方法方可启动线程并使线程进入就绪状态;而 run 方法只是 thread 的一个普通方法调用,还是在主线程里执行。 

如何证明 start() 会调用 run() 方法?

我们可以用一段简单的代码,通过调试来证明!

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            System.out.println("dsfdsfds");
        });
        t.start();
    }
}

start()方法上面打一个断点 

run()方法上面打一个断点  

通过调试发现,确实是会跳到run()里面! 但是具体怎么进去的?在IDEA中是看不出来的!因为这里是由JVM(C++写的)编写的,如果我们想要搞清楚它们是要去阅读JVM源码的!

JVM -> OS执行全流程 !!!

(1)使用 new Thread() 创建一个线程,然后调用 start0()方法 进行 Java 层面的线程启动

当我们自己写的代码使用 start() 方法的时候,表示启动这个线程,在该方法的内部会去调start0() 这个本地方法

(2)调用本地方法start0(),去调用 JVM 中的JVM_StartThread方法进行线程创建和启动

public
class Thread implements Runnable {
    private static native void registerNatives();
    static {
        registerNatives();
    }
    ...
}

start0() 会去调 JVM_StartThread 进行线程创建、启动,那它们是如何扯上关系的???

在 Java 中的 Thread 类,当我们初始化的时候(new的时候)会先执行静态代码块里的方法!

也就是说,会先调一下 registerNatives() 本地方法,如下图:

(3)调用 new JavaThread(&thread entry, sz) 进行线程的创建,并根据不同的操作系统平台调用对应的 os::create thread 方法进行线程创建

此时操作系统会切换为内核态!!! 

(4)新创建的线程状态为 lnitialized(初始化状态),调用了sync->wait() 的方法进行等待(先阻塞!!!),等到被唤醒才继续执行 thread->run()

等待JVM将其唤醒

(5)调用 Thread::start(native thread) 方法进行线程启动,此时将线程状态设置为RUNNABLE,接着调用 os::start_thread(thread),根据不同的操作系统选择不同的线程启动方式

(6)线程启动之后状态设置为RUNNABLE,并唤醒第4步中等待的线程,接着执行 thread->run() 的方法

(7) JavaThread::run()方法会回调第1步new Thread中复写的run()方法。

完整流程图 

 Thread#start()源码分析 流程图模板_ProcessOn思维导图、流程图

纵观整个流程,Java Thread --> JVM JavaThread --> OS Thread,在JVM操作OS创建线程时,会涉及到用户态到内核态的切换!!!这也是Java线程是一个很“”的操作的原因!!!

同样这也是Java线程池为什么优于多线程的原因!为什么要有线程复用机制的原因!!!

具体看这里 ↓ ↓ ↓

【并发】深入理解Java线程的底层原理_面向鸿蒙编程的博客-CSDN博客icon-default.png?t=M85Bhttps://blog.csdn.net/weixin_43715214/article/details/128099128

相关文章:

  • C++ 更常用 string 还是 char* 呢?
  • C数组
  • 【python】list 删除列表中某个元素的3种方法;附加删除numpy数组中的指定索引元素的方法
  • [C++]C++入门--引用
  • Power BI:在列表中点击详情按钮跳转到详情页面并传递参数
  • Nodejs -- Express中间件的概念及基本使用
  • 卡塔尔世界杯--程序员的诗和远方
  • 数据结构作业:传输数据的增删改
  • 1538_AURIX_TriCore内核架构_地址映射以及存储配置
  • 免费分享一个springboot+vue学生选课管理系统,挺漂亮的
  • 掌握这十个Linux命令,秒变Linux老手
  • ARM官方汇编与ARM GNU汇编中的伪操作
  • tensorflow-serving docker模型部署(以mnist为例)
  • Java#数据结构----1
  • 浅析数据采集工具Flume
  • 详解BFS,Dijkstra算法,Floyd算法是如何解决最短路径问题的
  • 零经验,小白变大厨!
  • 【路径规划】(2) A* 算法求解最短路,附python完整代码
  • 初识 Spring 框架
  • java计算机毕业设计高校心理测评管理系统源码+mysql数据库+系统+lw文档+部署
  • 市场监管总局出手整治涉企乱收费,聚焦政府部门及下属单位等领域
  • 中央党校(国家行政学院)举行2025年春季学期第一批进修班毕业典礼
  • 不准打小孩:童年逆境经历视角下的生育友好社会
  • 孕妇乘坐高铁突发临产,广西铁路部门协助送医平安产子
  • 华夏幸福:去年营业收入237.65亿元,同比减亏12亿元
  • 解放日报:中国大模型企业的发展机遇已经到来