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

聊一聊多线程的 run() 和 start(),挖一挖start0

首先是结论,应该大家知道:

调用start() 会触发多线程执行 ;

调用run() 还是当做执行了一个普通方法,没有多线程执行。

start()示例:

public class MyThread extends Thread {
    @SneakyThrows
    @Override
    public void run(){
        sleep(5000);
        System.out.println("run 内容打印 ");
    }

    public static void main(String[] args) {
        System.out.println("start 调用");
        MyThread testThread1=new MyThread();
        new Thread(testThread1,"线程1").start();
        System.out.println("主线程 最后的输出");
        
    }
}

结果:


run()示例:

public class MyThread extends Thread {
    @SneakyThrows
    @Override
    public void run(){
        sleep(5000);
        System.out.println("run 内容打印 ");
    }

    public static void main(String[] args) {
        System.out.println("run 调用");
        MyThread testThread2=new MyThread();
        new Thread(testThread2,"线程2").run();
        System.out.println("主线程 最后的输出");

    }
}

结果:

也就是咱们在使用多线程的时候要注意,调用run()是不正确的,不是我们想要的多线程效果。

那么我们应该调用 start() 。

我想问, 为什么?

为什么调用  start() 就是多线程  ?

ok,进入这篇文章的主题,一起挖源码 。

先看看java里面 start()的源码注释 :

使该线程开始执行;Java虚拟机 调用此线程的  run 方法。

结果是两个线程同时运行:

当前线程 start 和另一个线程(执行其运行方法)。

不用多说,大概也是告诉我们这个方法调用之后,是会触发多线程执行。


 再看看start方法,里面调用了 start0() ,然后没了。

那么可以知道 关键在于  start0() 。

可以看到这个start0 方法被 native 修饰着 。

native 关键字告诉编译器(其实是JVM)调用的是该方法在外部定义,这里指的是C。

也就是说光看java的源码是没办法找到 start0 ()的。

没事,既然进到我的文章,绝不会就此结束 。

openJDK源码 在线查阅地址 :
jdk8/jdk8/jdk: 687fd7c7986d /src/

锁定Thread.c

 来看看我们想找的相关源码,发现目标 start0:

在这里大致能知道,调用的是JVM的StartThread函数 。

也就是说我们需要去挖JVM的代码 ,Java 8, 使用的是 Oracle 的64位HotSpot虚拟机。

所以我直接下载HotSpot 源码。

锁定HotSpot 源码 :

找源码的过程我就省略了, 给出一些核心点,

可以看到里面 调用了 JavaThread :

再看看 JavaThread  :

看到这里,基本就差不多了锁定了 真的新创建了一个线程   create_thread 

 

大致就挖到这吧。可能这篇文章对大家帮助不大,但是对于跟我一样看源码有强迫症的人,多多少少心里会舒坦一些哈哈。

相关文章:

  • JAVA 继承Thread 实现多线程 资源不共享? 请保持清醒 。
  • SpringBoot 事件发布监听机制使用、分析、注意点 (一篇到位)
  • Springboot yml配置参数数据加密 (数据加密篇 一)
  • Springboot AOP实现指定敏感字段数据加密 (数据加密篇 二)
  • Springboot 使用mysql加密解密函数 (数据加密篇 三)
  • Java List数据量大, 需要分片批次操作
  • Springboot yml配置参数加密 ,jasypt自定义解密器(拓展篇)
  • Springboot 自定义mybatis 拦截器,实现我们要的扩展
  • Eureka 一直刷 Running the evict task with compensationTime 0ms
  • Eureka 注册、下线、续约事件的监听使用
  • Java Thread.sleep(),结合例子只学一次
  • Java ArrayList new出来,默认的容量到底是0还是10 ?
  • Mysql 关于 int(1) 和 int(11) , 我必须要说一下了。
  • SpringCloud 整合注册中心,配置中心 Nacos (九)
  • Springboot 自定义注解AOP实现时间参数格式转换
  • 【Leetcode】101. 对称二叉树
  • 77. Combinations
  • java2019面试题北京
  • js对象的深浅拷贝
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • python大佬养成计划----difflib模块
  • zookeeper系列(七)实战分布式命名服务
  • 悄悄地说一个bug
  • 如何实现 font-size 的响应式
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • kubernetes资源对象--ingress
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • 阿里云服务器如何修改远程端口?
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • (003)SlickEdit Unity的补全
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (第9篇)大数据的的超级应用——数据挖掘-推荐系统
  • (独孤九剑)--文件系统
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (四)Android布局类型(线性布局LinearLayout)
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)大型网站架构演变和知识体系
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET关于 跳过SSL中遇到的问题
  • .net经典笔试题
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • .NET值类型变量“活”在哪?
  • /proc/interrupts 和 /proc/stat 查看中断的情况