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

news2024/11/24 14:26:05

【面试题】深度解析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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/47354.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nodejs -- 数据库基本概念的介绍及在Express中操作数据库

文章目录1. 数据库的基本概念1.1 什么是数据库1.2 常见的数据库及分类1.3 传统型数据库的数据组织结构1.3.1 Excel的数据组织结构1.3.2 传统型数据库的数据组织结构1.3.3 实际开发中库、表、行、字段的关系2. 在Express中操作MySQL2.1 在项目中操作数据库的步骤2.2 安装与配置m…

Java编程案例:买飞机票

编程案例: 一、目的 复习前半段课程学习的Java编程知识,能够使用所学的知识解决问题,提升同学们的编程能力。 二、涉及到的知识点 变量、数组。运算符:基本运算符、关系运算符、逻辑运算符…程序流程控制:if、switc…

np.meshgrid()函数

文章目录(1)自己理解(2)官方解释(3)参数:3.1 x1, x2,…, xn:array_like3.2 sparse:bool, optional 默认false3.3 copy:bool, optional(1)自己理解 np.meshgrid(a, b,indexing "xy") 函数会返回 b.shape() 行 ,a.shape() 列的二维数组。 因此 i, j 都是 …

【序列召回推荐】(task6)多兴趣召回Comirec-SA

note Comirec-SA基于attention的多兴趣建模,论文中先通过attention提取单一兴趣,再推广到多兴趣建模。另外使用贪心算法优化带有准确度多样性的目标函数。DR把MIND的attention换成argmax(还有初始化方式不同、序列胶囊到兴趣胶囊用可学习权重…

2.线性代数基础

1.矩阵 2. 特殊矩阵 正交矩阵 AATE(E为单位矩阵,AT表示“矩阵A的转置矩阵”。)或ATAE,则n阶实矩阵A称为正交矩阵 正交矩阵有如下性质: A是正交矩阵,AT也是正交矩阵A的各行是单位向量且两两正交&#xff0…

html实现ezuikit.js萤石云直播监控,ezuikit.js实时监控实现,萤石云实时监控简单实现

效果图 实现 下面的播放url获取:登录萤石云->控制台->我的资源->设备列表->列表中:查看通道->监控地址 appKey和appSecret获取:登录萤石云->控制台->我的账号->应用信息->右侧:应用密钥 下载ezuikit…

(服务器客户端)网络通信是怎么实现的?7000字爆肝----原来java网络编程技术功不可没(多线程,URL,InetAddressm,TCP,UDP)集结

👨‍💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 收录于专栏 java ⭐java网络编程技术⭐ 文章目录⭐java网络编程技术⭐👨‍💻一,URL类…

[附源码]Python计算机毕业设计Django的4s店车辆管理系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

虎牙、斗鱼同道同命:共同御寒

配图来自Canva可画 回顾游戏直播行业过去十年,先是直播行业野蛮发展玩家快速跑马圈地,而后历经千播大战形成斗鱼、虎牙分天下的市场格局,现在头部平台进入精细化、多元化运作阶段,市场竞争愈加激烈。 也就是说,游戏直…

4G DTU能装4G物联网卡吗?

科技的发展日新月异,我们国家的发展战略也是支持高新科技公司的发展,所以越来越多的高新科技公司出现,但凡是高新科技公司,在设备的联网中,都会用到物联卡,所以物联卡的市场也愈发火爆,那么今天…

食物链【并查集+不知道1是A,B,C哪一类的?用x,x+n,x+n+n分别表示A,B,C中有个1】【并查集中用距离表示关系】【压缩路径】

欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录) 文章字体风格: 红色文字表示:重难点 蓝色文字表示:思…

jenkins项目构建类型 -----Pipeline流水线项目构建

壹,概念 pipeline 是一套运行在jenkins上得工作流框架,将原本运行于单个或者多个节点得任务连接起来,用来实现单个任务难以完成得复杂流程编排和可视化得工作。 贰 优点 代码持久可停止多功能可扩展 叁 如何创建Jenkins Pipeline pipeli…

计算机物联网控制|5.5常规控制方案 5.6先进控制方案

11.16日课堂作业 1.已知模拟PID算式为 试推导差分增量算式。 2.PID参数Kc、Ti、Td对系统动态特性和稳态特性有何影响? 目录 11.16日…

[附源码]计算机毕业设计springboot高校实验室仪器设备管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Telemetry原理

Telemetry是一种网络设备监控技术,提供周期采样网络设备内的统计数据和状态数据的能力。 一、Telemetry概述 1.1、技术背景: 网络设备的统一监控和性能管理是运维平台的重要功能,设备的监控数据包括数据、控制和管理平面数据。 获取设备监…

学习Python的8天

1、异常处理机制 Python 中,用try except语句块捕获并处理异常,其基本语法结构如下所示: try:可能产生异常的代码块 except [ (Error1, Error2, ... ) [as e] ]:#(e是别名,可以自己起)处理异常的代码块1 except [ (Error3, Error…

【强化学习论文合集 | 2020年合集】一. ICML-2020 强化学习论文

强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题。 本专栏整理了近几年国际顶级会议中,涉及强化学习(Rein…

Workfine使用Oracle Express Edition数据库

Workfine 应用环境和工具 Win10 专业版操作系统Windows Terminaldocker desktop 4.10.1 安装设置Oracle Express Edition数据库 1、获取Oracle XE 18.4.0 docker 镜像,在 Windows Terminal 终端里执行如下命令 docker pull gvenzl/oracle-xe:18.4.0 2、下载成功…

小啊呜产品读书笔记001:《邱岳的产品手记-14》第26讲 写好产品文档的诀窍 第27讲 产品案例分析: QuartzHooked的对话式交互

小啊呜产品读书笔记001:《邱岳的产品手记-14》第26讲 写好产品文档的诀窍 & 第27讲 产品案例分析: Quartz&Hooked的对话式交互一、今日阅读计划二、泛读&知识摘录1、第26讲 写好产品文档的诀窍2、第27讲 产品案例分析: Quartz&am…

web前端-javascript-function函数(函数说明,创建和调用函数,其他方法函数声明创建函数、函数表达式创建函数)

函数 //var fun new Function("console.log(Hello 这是我的第一个函数);"); //fun();function fun2() {console.log("这是我的第二个函数");alert("哈哈哈哈");document.write("~~~~(>_<)~~~~"); }//console.log(fun2); //调用…